/*
 * Copyright 2010  Marcin Szewczyk <Marcin.Szewczyk@wodny.org>
 * 
 * This file is part of the Page Portal project.
 * 
 * Page Portal is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Page Portal is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Page Portal.  If not, see <http://www.gnu.org/licenses/>.
 */



var page_prefix = "book/page-";
var page_suffix = ".png";
var page_number = 0;
var padding = 3;


$(document).ready(function(){
  //////////////////////////////////////////
  // Navigation events                    //
  //////////////////////////////////////////

  $("#go_button").button().click(function() {
    reset_document();
  });

  $("#prev").click(function(event){
    event.preventDefault();
    if(page_number <= 0) return;
    update_page(parseInt(page_number)-1);
  }).button();

  $("#next").click(function(event){
    event.preventDefault();
    update_page(parseInt(page_number)+1);
  }).button();

  $("#page_number").keypress(function(event){
    if(event.keyCode == 13) {
      //event.preventDefault();
      update_page( $("#page_number").attr("value") );
    }
  });

  //////////////////////////////////////////
  // Document and page manipulation       //
  //////////////////////////////////////////

  function pad(number, padding) {
    var number = new String(number);
    var padding = padding - number.length;
    padding = (padding < 0) ? 0 : padding;
    for(var i = padding; i > 0; --i)
      number = "0" + number;
    return number;
  }

  function get_page_src(prefix, p) {
    return prefix+pad(p, padding)+page_suffix;
  }

  function update_page(pn) {
    page_number = pn;
    $("#page_number").attr("value", page_number);
    $("#mainpage").attr("src", get_page_src(page_prefix, page_number));
  }

  function get_docurl() {
    return $("#document_url").attr("value");
  }

  function reset_document() {
    page_prefix = get_docurl();
    $("#mainpage").attr("src", "img/logo.png");
    update_page(0);
  }

  reset_document();

  //////////////////////////////////////////
  // Marker associated with a portal      //
  //////////////////////////////////////////
  
  function set_marker(portal) {
        if(portal.data("page_number") != page_number) return;

        var page_container = portal.find(".portal_page_container");

        var page = portal.find(".portal_page");
        var pagepos = page.position();
        var mpage = $("#mainpage");
        var mpagepos = mpage.position();
        var marker = $("#marker");

       
        var xp_s;
        var yp_s;
        var xp_e;
        var yp_e;
        if(page_container.is(':hidden')) {
          xp_s = portal.data("xp_s");
          yp_s = portal.data("yp_s");
          xp_e = portal.data("xp_e");
          yp_e = portal.data("yp_e");
        } else {
          xp_s = -pagepos.left / page.width();
          yp_s = -pagepos.top  / page.height();
          xp_e = (-pagepos.left + page_container.width() ) / page.width();
          yp_e = (-pagepos.top  + page_container.height()) / page.height();
          portal.data("xp_s", xp_s);
          portal.data("yp_s", yp_s);
          portal.data("xp_e", xp_e);
          portal.data("yp_e", yp_e);
        }
        var l = xp_s * mpage.width()  + mpagepos.left;
        var t = yp_s * mpage.height() + mpagepos.top;
        var w = xp_e * mpage.width()  - xp_s * mpage.width();
        var h = yp_e * mpage.height() - yp_s * mpage.height();
        marker.css("left", l);
        marker.css("top",  t);
        marker.css("width", w);
        marker.css("height", h);
        marker.css("visibility", "visible");
  }

  //////////////////////////////////////////
  // Portal creation                      //
  //////////////////////////////////////////
  
  function creation_progress_update(delta) {
    creation_progress_update.toload += delta;
    if(creation_progress_update.toload > 0) {
      storage_status(creation_progress_update.toload + " portals remaining...");
    } else {
      if(creation_progress_update.queuefull)
        storage_status("Done creating portals.");
    }
  }

  creation_progress_update.toload = 0;
  creation_progress_update.queuefull = false;

  // Wrapper function, sets default based on the current main page
  function create_portal(prefix, p, title, x, y, width, height, scale, inoffset) {
    var portal = $("#factory .portal").clone();
    
    // Defaults
    portal.data("prefix", prefix === null ? page_prefix : prefix);
    portal.data("page_number", p === null ? page_number : p);
    portal.find("input").attr("value", title === null ? "a portal" : title);

    var defwidth = 300;
    var defheight = 300;
    if(width === null) {
      width = defwidth;
      y -= defwidth/2;
    }
    if(height === null) {
      height = defheight;
      x -= defheight/2;
    }

    var img = new Image();
    $(img).load(function() {
      var img = this;
      var mpage = $("#desktop img");
      var mpagepos = mpage.position();
  
      creation_progress_update(-1);

      portal.data("origpagewidth", img.width);
      scale = (scale === null) ? mpage.width() / img.width : scale;
      var page_width = img.width * scale;
  
      inoffset = (inoffset === null) ? {'x': mpagepos.left - x, 'y': mpagepos.top - y} : inoffset;
  
      init_portal(portal, title, x, y, width, height, scale, page_width, inoffset);
    });

    creation_progress_update(1);
    img.src = get_page_src(portal.data("prefix"), portal.data("page_number"));
  }

  function init_portal(portal, title, x, y, width, height, scale, page_width, inoffset) {
    // Some constants
    var minwidth = 130;
    var minheight = 30;

    // Features
    portal.draggable();

    // Marker feature
    portal.mouseover(function(){
      var portal = $(this).closest(".portal");
      set_marker(portal);
    });
    portal.mouseout(function(){
      $("#marker").css("visibility", "hidden");
    });

    var page_container = portal.find(".portal_page_container").resizable({
      'minWidth': minwidth,
      'minHeight': minheight,
      stop: function() {
        var portal = $(this).closest(".portal");
        set_marker(portal);
      }
    });
    var page = portal.find(".portal_page").draggable({
      stop: function() {
        var portal = $(this).closest(".portal");
        set_marker(portal);
      }
    });


    // Portal zoom
    function set_portal_zoom(slider, ui) {
        var portal = slider.closest(".portal");
        var page_container = portal.find(".portal_page_container");
        var page = portal.find(".portal_page");
        var pagepos = page.position();

        var hor_p =  (page_container.width()/2 -  pagepos.left) / page.width();
        var vert_p = (page_container.height()/2 - pagepos.top)  / page.height();

        page.width( ui.value * portal.data("origpagewidth") / 100 );

        page.css("left", page_container.width()/2  - hor_p  * page.width());
        page.css("top",  page_container.height()/2 - vert_p * page.height());
       
        set_marker(portal);
    }
    portal.find(".zoom_slider").slider({
      'min': 10,
      'max': 200,
      slide: function(event, ui) {
        set_portal_zoom($(this), ui);
      },
      change: function(event, ui) {
        set_portal_zoom($(this), ui);
      }
    }).slider("value", scale * 100);

    var zoom_marker = portal.find(".zoom_marker");
    zoom_marker.css("left", ((scale*100-10)/(200-10))*100+"%");
    zoom_marker.click(function(){
      var slider = $(this).closest(".portal").find(".zoom_slider");
      slider.slider("value", parseFloat($(this).css("left"))*(200-10)/100+10);
    });

    // GoTo button
    portal.find(".gotobutton").button({text: false, icons: {primary: "ui-icon-arrow-1-e"}}).click(
      function() {
        update_page( $(this).closest(".portal").data("page_number") );
      }
    );

    // Hide button
    portal.find(".hidebutton").button({text: false, icons: {primary: "ui-icon-newwin"}}).click(
      function() {
        $(this).closest(".portal").find(".portal_page_container").toggle("drop", {}, "fast");
      }
    );

    // Close button
    portal.find(".closebutton").button({text: false, icons: {primary: "ui-icon-close"}}).click(
      function() {
         $(this).closest(".portal").remove();
         $("#marker").css("visibility", "hidden");
      }
    );

    // Portal coords
    portal.css("position", "absolute"); // Opera
    portal.css("left", x+"px");
    portal.css("top", y+"px");
    // Transfer page to portal
    page.attr("src", get_page_src(portal.data("prefix"), portal.data("page_number")));
    page.width(page_width);

    page_container.css("width", (width < minwidth) ? minwidth : width);
    page_container.css("height", (height < minheight) ? minheight : height);
    
    // Append portal to DOM
    $("#desktop").append(portal);

    // Style calculated at this point

    // Final adjustments
    page.css("left", inoffset.x+"px");
    page.css("top",  inoffset.y+"px");
    portal.css("visibility", "visible");
  }

  //////////////////////////////////////////
  // Main page events                     //
  //////////////////////////////////////////
  
  function pageclick(event) {
    create_portal(null, null, null, event.pageX, event.pageY, null, null, null, null);
  }

  $("#mainpage").click(pageclick);
  $("#mainpage").selectable({
    distance : 5,
    start : function(event, ui) {
      $(this).data("start", {'x': event.pageX, 'y': event.pageY});
      $("#mainpage").unbind('click'); // Opera
    },
    stop : function(event, ui) {
      var start = $(this).data("start");
      create_portal(null, null, null,
                    start.x < event.pageX ? start.x : event.pageX,
                    start.y < event.pageY ? start.y : event.pageY,
                    Math.abs(event.pageX-start.x),
                    Math.abs(event.pageY-start.y),
                    null, null);
      setTimeout(function(){
        $("#mainpage").click(pageclick)
      }, 300); // Opera
    }
  });

  //////////////////////////////////////////
  // Global zoom slider                   //
  //////////////////////////////////////////

  $("#main_zoom_slider").slider({
    'min': 50,
    'max': 300,
    'value': 100,
    'range': "min",
    'orientation': "vertical",
    stop: function(event, ui) {
      $("#mainpage").css("height", ui.value+'%');
    }
  });

  //////////////////////////////////////////
  // Storage                              //
  //////////////////////////////////////////
  
  // Features
  $("#storage_tabs").tabs();

  // Events: show storage dialog
  $("#storage_button").button().click(
    function() {
      storage_status("Ready.");
      var width = $(document).width() * .4;
      $("#storage_dialog").dialog({
        title: "Storage",
        width: width,
        modal: true,
        buttons: {
          Close: function() {
            $(this).dialog('close');
          },
        }
      });
    }
  );

  // Utility functions
  function storage_status(status) {
    $("#storage_status").text(status);
    if($("#storage_status").is(":hidden"))
      $("#storage_status").show("drop");
    clearTimeout(storage_status.timeout);
    storage_status.timeout = setTimeout(
      function() {
        //$("#storage_status").hide("drop", {}, "fast", storage_status_hidden);
        $("#storage_status").hide("drop", {}, "fast");
      }, 4000
    );
  }

  function serialize_portals() {
    var portals = [];
    $("#desktop .portal").each(function(idx, elem) {
      var portal = $(this);
      var page_container = portal.find(".portal_page_container");
      var page = portal.find(".portal_page");
      var pdata  = portal.data("page_number")+",";
      pdata += portal.position().left+",";
      pdata += portal.position().top+",";
      pdata += page_container.width()+",";
      pdata += page_container.height()+",";
      pdata += encodeURIComponent(portal.find("input").attr("value"))+",";
      pdata += (portal.find(".zoom_slider").slider('value') / 100)+",";
      pdata += page.css("left")+",";
      pdata += page.css("top");
      portals.push(encodeURIComponent(pdata));
    });
    return encodeURIComponent(portals.join(","));
  }

  function deserialize_portals(data) {
    var docurl = get_docurl();
    var portals = decodeURIComponent(data).split(',');
    creation_progress_update.queuefull = false;
    for (var i=0; i<portals.length; ++i) {
      var portal = portals[i];
      var parts = decodeURIComponent(portal).split(',');
      if(parts.length != 9) continue;
      var page = parseInt(parts[0]);
      var left = parseInt(parts[1]);
      var top = parseInt(parts[2]);
      var width = parseInt(parts[3]);
      var height = parseInt(parts[4]);
      var title = decodeURIComponent(parts[5]);
      var scale = parseFloat(parts[6]);
      var inoffset = {'x': parseInt(parts[7]), 'y': parseInt(parts[8])};
      storage_status(title+"...");
      create_portal(docurl, page, title, left, top, width, height, scale, inoffset);
    }
    creation_progress_update.queuefull = true;
    creation_progress_update(0); // if all have loaded, "Done" would be lost
  }

  // Load

  $("#load_clear").click(function() {
    $("#desktop .portal").each(function(idx, elem) {
      $(this).remove();
    });
  });

  $("#load_cookies").click(
    function() {
      storage_status("Loading from cookies...");
      var docurl = get_docurl();
      var cookies = document.cookie.split(";");
      for (var i=0; i<cookies.length; ++i) {
        var cookie = cookies[i];
        if(cookie.split('=')[0] == encodeURIComponent(docurl)) {
          deserialize_portals(cookie.split('=')[1]);
          storage_status("Done.");
          return;
        }
      }
      storage_status("No cookies associated with this book.");
    }
  );

  $("#load_lstorage").click(
    function() {
      storage_status("Loading from localStorage...");
      if(typeof localStorage == "undefined") {
        storage_status("LocalStorage unavailable.");
        return;
      }
      var docurl = get_docurl();
      if(localStorage[encodeURIComponent(docurl)]) {
        deserialize_portals(localStorage[encodeURIComponent(docurl)]);
        storage_status("Done.");
      } else {
        storage_status("Book doesn't exist in the localStorage.");
      }
    }
  );

  $("#load_text").click(
    function() {
      storage_status("Loading from text...");
      deserialize_portals($("#load_text_body").attr("value"));
      storage_status("Done.");
    }
  );

  // Save

  $("#save_cookies").click(
    function() {
      storage_status("Saving to cookies...");
      var docurl = encodeURIComponent(page_prefix);
      document.cookie = docurl+"="+serialize_portals()+";max-age=315360000";
      storage_status("Done.");
    }
  );

  $("#save_lstorage").click(
    function() {
      storage_status("Saving to localStorage...");
      var docurl = encodeURIComponent(page_prefix);
      if(typeof localStorage == "undefined") {
        storage_status("LocalStorage unavailable.");
        return;
      }
      localStorage[docurl] = serialize_portals();
      storage_status("Done.");
    }
  );

  $("#save_text").click(
    function() {
      storage_status("Saving to text...");
      $("#save_text_body").attr("value", serialize_portals());
      storage_status("Done.");
    }
  );

});

