// Things to abstract out to another file

// We do sync AJAX for just the page close event. 
// TODO: This should _really_ not be a global. 
var log_close_event = false; 

function log_close() {
    var d=new Date();
    var t=d.getTime();
    //close_event_logged = "waiting";
    log_close_event = true;
    log_event('page_close', {});
    log_close_event = false;
    // Google Chrome will close without letting the event go through.
    // This causes the page close to be delayed until we've hit the
    // server. The code below fixes it, but breaks Firefox. 
    // TODO: Check what happens with no network. 
    /*while((close_event_logged != "done") && (d.getTime() < t+500)) {
	console.log(close_event_logged);
    }*/
}

window.onbeforeunload = log_close;

function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie != '') {
	var cookies = document.cookie.split(';');
	for (var i = 0; i < cookies.length; i++) {
	    var cookie = jQuery.trim(cookies[i]);
	    // Does this cookie string begin with the name we want?
	    if (cookie.substring(0, name.length + 1) == (name + '=')) {
		cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
		break;
	    }
	}
    }
    return cookieValue;
}

function postJSON(url, data, callback) {
    $.ajax({type:'POST',
	    url: url,
		dataType: 'json',
		data: data,
		success: callback,
		headers : {'X-CSRFToken':getCookie('csrftoken')}
  });
}

function postJSONAsync(url, data, callback) {
    $.ajax({type:'POST',
	    url: url,
		dataType: 'json',
		data: data,
		success: callback,
		headers : {'X-CSRFToken':getCookie('csrftoken')},
		async:true
		});
}

// For easy embedding of CSRF in forms
$(function() {
    $('#csrfmiddlewaretoken').attr("value", getCookie('csrftoken'))
});

// For working with circuits in wiki: 

function submit_circuit(circuit_id) {
    $("input.schematic").each(function(index,element){ element.schematic.update_value(); });
    postJSON('/save_circuit/'+circuit_id, 
	     {'schematic': $('#schematic_'+circuit_id).attr("value")}, 
	     function(data){ if (data.results=='success') alert("Saved");});
    return false;
}

// Video player

var load_id = 0;
var caption_id;
var video_speed = "1.0";

var updateytPlayerInterval;
var ajax_videoInterval;

function change_video_speed(speed, youtube_id) {
    new_position = ytplayer.getCurrentTime() * video_speed / speed;
    video_speed = speed;
    ytplayer.loadVideoById(youtube_id, new_position);
    syncPlayButton();
    log_event("speed", {"new_speed":speed, "clip":youtube_id});

    $.cookie("video_speed", speed, {'expires':3650, 'path':'/'});
}

function caption_at(index) {
    if (captions==0)
	return "";

    text_array=captions.text

    if ((index>=text_array.length) || (index < 0))
	return "";
    return text_array[index];
}

function caption_time_at(index) {
    if (captions==0)
	return 0;

    time_array=captions.start;

    if (index < 0)
	return 0;
    if (index>=time_array.length)
	return ytplayer.getDuration();

    return time_array[index] / 1000.0 / video_speed;
}

function caption_index(now) {
    // Returns the index of the current caption, given a time
    now = now * video_speed;

    if (captions==0)
	return 0;

    time_array=captions.start

    // TODO: Bisection would be better, or something incremental
    var i; 
    for(i=0;i<captions.start.length; i++) {
	if(time_array[i]>(now*1000)) {
	    return i-1;
	}
    }
    return i-1;
}

function format_time(t)
{
    seconds = Math.floor(t);
    minutes = Math.floor(seconds / 60);
    hours = Math.floor(minutes / 60);
    seconds = seconds % 60;
    minutes = minutes % 60;

    if (hours) {
      return hours+":"+((minutes < 10)?"0":"")+minutes+":"+((seconds < 10)?"0":"")+(seconds%60);
    } else {
      return minutes+":"+((seconds < 10)?"0":"")+(seconds%60);
    }
}

function update_captions(t) {
    var i=caption_index(t);
    $("#vidtime").html(format_time(ytplayer.getCurrentTime())+' / '+format_time(ytplayer.getDuration()));
    var j;
    for(j=1; j<9; j++) {
	$("#std_n"+j).html(caption_at(i-j));
	$("#std_p"+j).html(caption_at(i+j));
    }
    $("#std_0").html(caption_at(i));
}

function title_seek(i) {
    // Seek video forwards or backwards by i subtitles
    current=caption_index(getCurrentTime());
    new_time=caption_time_at(current+i);
    
    ytplayer.seekTo(new_time, true);
}

function updateHTML(elmId, value) {
    document.getElementById(elmId).innerHTML = value;
}

function setytplayerState(newState) {
    //    updateHTML("playerstate", newState);
}

// Updates server with location in video so we can resume from the same place
// IMPORTANT TODO: Load test
// POSSIBLE FIX: Move to unload() event and similar
var ajax_video=function(){};
var ytplayer;

function onYouTubePlayerReady(playerId) {
    ytplayer = document.getElementById("myytplayer");
    updateytplayerInfoInterval = setInterval(updateytplayerInfo, 500);
    ajax_videoInterval = setInterval(ajax_video,5000);
    ytplayer.addEventListener("onStateChange", "onytplayerStateChange");
    ytplayer.addEventListener("onError", "onPlayerError");
    if((typeof load_id != "undefined") && (load_id != 0)) {
	var id=load_id;
	loadNewVideo(caption_id, id, 0);
    }
}

/* HTML5 YouTube iFrame API Specific */
function onYouTubePlayerAPIReady() {
  ytplayer = new YT.Player('html5_player', {
    events: { 
      'onReady': onPlayerReady,
      'onStateChange': onPlayerStateChange
    }
  });
  updateytplayerInfoInterval = setInterval(updateHTML5ytplayerInfo, 200);
  //ajax_videoInterval = setInterval(ajax_video, 5000);
}

// Need this function to call the API ready callback when we switch to a tab with AJAX that has a video
// That callback is not being fired when we switch tabs. 
function loadHTML5Video() {
    if (!ytplayer && switched_tab){
      onYouTubePlayerAPIReady();
    }
}

function isiOSDevice(){
  var iphone = "iphone";
  var ipod = "ipod";
  var ipad = "ipad";
  var uagent = navigator.userAgent.toLowerCase();

  //alert(uagent);
  if (uagent.search(ipad) > -1 || uagent.search(iphone) > -1
      || uagent.search(ipod) > -1) {
    return true;
  }
  return false;
}

function onPlayerReady(event) {
  //do not want to autoplay on iOS devices since its not enabled
  //and leads to confusing behavior for the user
  if (!isiOSDevice()) {
    event.target.playVideo();
  }
}

function onPlayerStateChange(event) {
  if (event.data == YT.PlayerState.PLAYING) {
  }
}

/* End HTML5 Specific */


var switched_tab = false; // switch to true when we destroy so we know to call onYouTubePlayerAPIReady()
// clear pings to video status when we switch to a different sequence tab with ajax
function videoDestroy(id) {
//    postJSON('/modx/video/'+id+'/goto_position',
//	     {'position' :  ytplayer.getCurrentTime()});

    load_id = 0;
    clearInterval(updateytplayerInfoInterval);
    clearInterval(ajax_videoInterval);
    ytplayer = false;
    switched_tab = true;
}

function log_event(e, d) {
    data = {
	"event_type" : e, 
	"event" : JSON.stringify(d),
	"page" : document.URL
    }
    $.ajax({type:'GET',
	    url: '/event',
	    dataType: 'json',
	    data: data,
	    async: !log_close_event, // HACK: See comment on log_close_event
	    success: function(){},
	    headers : {'X-CSRFToken':getCookie('csrftoken')}
	   });

    /*, // Commenting out Chrome bug fix, since it breaks FF
	  function(data) {
	      console.log("closing");
	      if (close_event_logged == "waiting") {
		  close_event_logged = "done";
	      console.log("closed");
	  }
	  });*/
}

function seek_slide(type,oe,value) {
    //log_event('video', [type, value]);
    if(type=='slide') {
	 // HACK/TODO: Youtube recommends this be false for slide and true for stop.
	 // Works better on my system with true/true. 
	 // We should test both configurations on low/high bandwidth 
	 // connections, and different browsers
	 // One issue is that we query the Youtube window every 250ms for position/state
	 // With false, it returns the old one (ignoring the new seek), and moves the
         // scroll bar to the wrong spot. 
	ytplayer.seekTo(value, true);
    } else if (type=='stop') {
	ytplayer.seekTo(value, true);
	log_event('video', [type, value]);
    }

    update_captions(value);
}

function get_state() {
    if (ytplayer)
	return [ytplayer.getPlayerState(),
		ytplayer.getVideoUrl(),
		ytplayer.getDuration(), ytplayer.getCurrentTime(), 
		ytplayer.getVideoBytesLoaded(), ytplayer.getVideoBytesTotal(), 
		ytplayer.getVideoStartBytes(), 
		ytplayer.getVolume(),ytplayer.isMuted(),
		ytplayer.getPlaybackQuality(),
		ytplayer.getAvailableQualityLevels()];
    return [];
}

function onytplayerStateChange(newState) {
    setytplayerState(newState);
    log_event('video', ['State Change',newState, get_state()]);
}

function onPlayerError(errorCode) {
    //    alert("An error occured: " + errorCode);
    log_event("player_error", {"error":errorCode});
}

// Currently duplicated to check for if video control changed by clicking the video for HTML5
// Hacky b/c of lack of control over YT player
function updateHTML5ytplayerInfo() {
    var player_state = getPlayerState();
    if(player_state != 3) {
      $("#slider").slider("option","max",ytplayer.getDuration());
      $("#slider").slider("option","value",ytplayer.getCurrentTime());
    }
    if (player_state == 1){
      update_captions(getCurrentTime());
    }
    if (player_state == 1 && $("#video_control").hasClass("play"))
      $("#video_control").removeClass().addClass("pause");
    else if (player_state == 2 && $("#video_control").hasClass("pause"))
      $("#video_control").removeClass().addClass("play");
}

function updateytplayerInfo() {
    var player_state = getPlayerState();
    if(player_state != 3) {
      $("#slider").slider("option","max",ytplayer.getDuration());
      $("#slider").slider("option","value",ytplayer.getCurrentTime());
    }
    if (player_state == 1){
      update_captions(getCurrentTime());
    }
       // updateHTML("videoduration", getDuration());
    //    updateHTML("videotime", getCurrentTime());
    //    updateHTML("startbytes", getStartBytes());
    //    updateHTML("volume", getVolume());
}

// functions for the api calls
function loadNewVideo(cap_id, id, startSeconds) {
    captions={"start":[0],"end":[0],"text":["Attempting to load captions..."]};
    $.getJSON("/static/subs/"+cap_id+".srt.sjson", function(data) {
        captions=data;
    });
    caption_id = cap_id;
    load_id = id;
    //if ((typeof ytplayer != "undefined") && (ytplayer.type=="application/x-shockwave-flash")) {
    // Try it every time. If we fail, we want the error message for now. 
    // TODO: Add try/catch
    try {
	ytplayer.loadVideoById(id, parseInt(startSeconds));
        load_id=0;
    }
    catch(e) {
	window['console'].log(JSON.stringify(e));
    }
    log_event("load_video", {"id":id,"start":startSeconds});
    //$("#slider").slider("option","value",startSeconds);
    //seekTo(startSeconds);
}

function syncPlayButton(){
  var state = getPlayerState();
  if (state == 1 || state == 3) {
    $("#video_control").removeClass("play").addClass("pause");
  } else if (state == 2 || state == -1 || state == 0){
    $("#video_control").removeClass("pause").addClass("play");
  }
}

function cueNewVideo(id, startSeconds) {
    if (ytplayer) {
	ytplayer.cueVideoById(id, startSeconds);
    }
}

function play() {
    if (ytplayer) {
	ytplayer.playVideo();
    }
    log_event("play_video", {"id":getCurrentTime(), "code":getEmbedCode()});
}

function pause() {
    if (ytplayer) {
	ytplayer.pauseVideo();
    }
    log_event("pause_video", {"id":getCurrentTime(), "code":getEmbedCode()});
}

function stop() {
    if (ytplayer) {
	ytplayer.stopVideo();
    }
    log_event("stop_video", {"id":getCurrentTime(), "code":getEmbedCode()});
}

function getPlayerState() {
    if (ytplayer) {
	return ytplayer.getPlayerState();
    }
}

function seekTo(seconds) {
    if (ytplayer) {
	ytplayer.seekTo(seconds, true);
    }
}

function getBytesTotal() {
    if (ytplayer) {
	return ytplayer.getVideoBytesTotal();
    }
}

function getCurrentTime() {
    if (ytplayer) {
	return ytplayer.getCurrentTime();
    }
}

function getDuration() {
    if (ytplayer) {
	return ytplayer.getDuration();
    }
}

function getStartBytes() {
    if (ytplayer) {
	return ytplayer.getVideoStartBytes();
    }
}

function mute() {
    if (ytplayer) {
	ytplayer.mute();
    }
}

function unMute() {
    if (ytplayer) {
	ytplayer.unMute();
    }
}

function getEmbedCode() {
    if(ytplayer) {
	ytplayer.getVideoEmbedCode();
    }
}

function getVideoUrl() {
    if(ytplayer) {
	ytplayer.getVideoUrl();
    }
}

function setVolume(newVolume) {
    if (ytplayer) {
	ytplayer.setVolume(newVolume);
    }
}

function getVolume() {
    if (ytplayer) {
	return ytplayer.getVolume();
    }
}

function clearVideo() {
    if (ytplayer) {
	ytplayer.clearVideo();
    }
}
