;(function($){
  var updateCache = function() {
		console.log("updateCache");
    var webappCache = window.applicationCache,
			loader = {display:''},cacheStarted = false;
		
		$(function() {
      //loader = $("#loader")[0].style;
    });
		
		function noupdateCache() {
		  cacheStarted = true;
      console.log("noupdateCache");
      loader.display = "none";
      initDb();
		}
		function doneCache() {
		  console.log("doneCache");
      loader.display = "none";
      initDb();
		}
		function progressCache() {
		  cacheStarted = true;
		  //console.log("progressCache");
      loader.display = "table";
		}
		function updateCache() {
			console.log("updateCache");
      try{
        webappCache.swapCache();
      } catch(e) {};
      loader.display = "none";
			console.log("reloading");
      window.location.reload();
		}
		function errorCache() {
		  console.log("errorCache");
      loader.display = "none";
      initDb();
		}
		webappCache.addEventListener("progress", progressCache, false);
		webappCache.addEventListener("cached", doneCache, false);
		webappCache.addEventListener("noupdate", noupdateCache, false);
		webappCache.addEventListener("updateready", updateCache, false);
		webappCache.addEventListener("error", errorCache, false);
		console.log("cache status "+webappCache.status);
    if(webappCache.status==1)
      window.setTimeout(function() {
        if(webappCache.status==1 && !cacheStarted) {
    		  console.log("cache is idle...start initing db");
          initDb();
    		}
    	},100);
    if(webappCache.status==0)
      initDb();
  }
  
  var db,
      bootDbLoaded = false,
      currentVersion = "0.8",
      originVersion;
  
  function initDb() {
    console.log("initDb start");
    var shortName = 'rollDemo';
    var displayName = 'Roll Demo Database';
    var maxSize = 10*1024*1024; // in bytes
    console.log("Opening db");
    try {
      db = openDatabase(shortName, "0.1", displayName, maxSize);
      getDbVersion(createDb);
    } catch(e) {
      console.log("openDatabase error: "+e.message);
    }
  }
  
  function getDbVersion(callback) {
    db.transaction(function(t){
      t.executeSql("SELECT * from Meta",[],
      function(t,data){
        var res = resultSetToHash(data);
        originVersion = res[0].versione;
        console.log("db version "+originVersion);
        callback();
      });
    },
    function(error){
      console.log("No db version");
      callback();
    });
  }
  
  function createDb() {
    if(!originVersion) {
      console.log("Creating db");
      db.transaction(function(t) {
          //se esistevano tabelle pre-versioning, cancellale
          t.executeSql("DROP TABLE IF EXISTS Meta");
          t.executeSql("CREATE TABLE Meta (versione NVARCHAR(255),timestamp INTEGER,timestamp_ex CLOB)");
          t.executeSql("INSERT INTO Meta (versione) VALUES('"+currentVersion+"')");
          t.executeSql("DROP TABLE IF EXISTS Lavori");
          t.executeSql("CREATE TABLE Lavori (idLavoro INTEGER PRIMARY KEY,titolo NVARCHAR(255),descrizione NVARCHAR(255),url NVARCHAR(255),data NVARCHAR(255))");          t.executeSql("DROP TABLE IF EXISTS Immagini");
          t.executeSql("CREATE TABLE Immagini (idImmagine INTEGER PRIMARY KEY,idLavoro INTEGER,img CLOB,descrizione CLOB,ord INTEGER)");
          t.executeSql("CREATE TABLE Gallery (idImmagine INTEGER PRIMARY KEY,idLavoro INTEGER,img CLOB,descrizione CLOB,ord INTEGER)");
      },
      function(e){
        console.log("errore creazione db "+e.message+" db version "+db.version);    
      },
      function() {
        detectOnLine("Lavori");
      });
    } else if(originVersion != currentVersion) {
      console.log("db version change detected");
      db.transaction(function(t) {
        changeDb(t);
      },
      function(e) {
        console.log("errore aggiornamento db da "+db.version+" a "+currentVersion+" "+e.message);
      },
      function() {
        detectOnLine("Lavori");
      });
    } else {
      console.log("no db version change detected");
      detectOnLine("Lavori");
    }
  }
  
  function changeDb(t) {
    console.log("changing db version from "+originVersion+ " to "+currentVersion);
    if(originVersion=='0.3') {
      t.executeSql("ALTER TABLE Meta ADD COLUMN timestamp INTEGER");
    }
    if(originVersion=='0.4') {
      t.executeSql("DROP TABLE Immagini");
      t.executeSql("CREATE TABLE Immagini (idImmagine INTEGER PRIMARY KEY,idLavoro INTEGER,img CLOB,descrizione CLOB,ord INTEGER)");
      t.executeSql("UPDATE Meta SET timestamp=null");//devo ricaricare tutti i dati
    }
    if(originVersion=='0.5') {
      t.executeSql("ALTER TABLE Lavori ADD COLUMN data NVARCHAR(255)");
      t.executeSql("UPDATE Meta SET timestamp=null");//devo ricaricare tutti i dati
    }    
    if(originVersion=='0.6') {
      t.executeSql("CREATE TABLE Gallery (idImmagine INTEGER PRIMARY KEY,idLavoro INTEGER,img CLOB,descrizione CLOB,ord INTEGER)");
      t.executeSql("UPDATE Meta SET timestamp=null");//devo ricaricare tutti i dati
    }    
    if(originVersion=='0.7') {
      t.executeSql("ALTER TABLE Meta ADD COLUMN timestamp_ex CLOB");
    }
    t.executeSql("UPDATE Meta SET versione= '"+currentVersion+"'");
  }
  
  function detectOnLine(table) {
    console.log("detectOnLine");
    if(window.navigator.onLine)
      loadData(table);
    else {
      bootDbLoaded = true;
      $(document).trigger("dataReady");
    }
  }
  
  function loadData(table) {
    try {
      doSelect("SELECT timestamp_ex from META",[],function(data){
        var timestamp_ex = data[0].timestamp_ex?eval("("+data[0].timestamp_ex+")"):{};
        var timestamp = timestamp_ex["_"+table] || "";
        var tableurl = table? "&table="+table : "";
        console.log("loading ajax");
        $.ajax({url:"http://iphone.rollstudio.it/rollup/data/spip.php?page=rolldb2&timestamp="+timestamp+tableurl,success:function(json) {insertData(json,table,timestamp_ex);},error:loadDataError,dataType:"json",cache:false});
      })
    } catch(e) {
      console.log("ajax error");
      bootDbLoaded = true;
      $(document).trigger("dataReady");
    }
  }
  
  function loadDataError(XHR,t,e) {
    console.log("loadData Error "+t+" "+e);
    bootDbLoaded = true;
    $(document).trigger("dataReady");
  }
  
  function insertData(json,table,timestamp_ex) {
    console.log("insertData");
    db.transaction(function(t){
      $.each(json.tabelle,function(i,tabella){
        /*
        console.log("cancello dati tabella "+tabella.nome);
        var sql = "DELETE FROM "+tabella.nome;
        t.executeSql(sql,[],function(){},function(tx,error){
          console.log(error.message);
        });
        */
        var sql = "", ids = tabella.ids.join(",");
        //console.log("cancello righe non più esistenti");
        sql = "DELETE FROM "+tabella.nome+" WHERE "+tabella.nome_id+" NOT IN ("+ids+")";
        t.executeSql(sql,[],function(){},function(tx,error){
          console.log(error.message);
        });
        $.each(tabella.dati,function(i,riga) {
          //console.log("inserisco riga");
          sql = "INSERT OR REPLACE INTO "+tabella.nome+" (";
          var nomi= [],valori = [];
          $.each(riga,function(nome,valore) {
            nomi.push(nome);
            valori.push(valore);
          });
          nomi = nomi.join(",");
          valori = "'"+valori.join("','")+"'";
          sql += nomi+") VALUES("+valori+")";
          t.executeSql(sql,[],function(){},function(tx,error){
            console.log(error.message);
          });
        });
      });
      timestamp_ex["_"+table] = json.timestamp;
      var props = [];
      for(prop in timestamp_ex) {
        props.push("\""+prop+"\":\""+timestamp_ex[prop]+"\"");
      }
      var str = "{"+props.join(",")+"}";
      t.executeSql("UPDATE Meta SET timestamp_ex='"+str+"'");
    },
    function(){
      console.log("error inserting data");
      bootDbLoaded = true;
      $(document).trigger("dataReady");   
    },
    function(){
      console.log("dataInserted");
      bootDbLoaded = true;
      $(document).trigger("dataReady");
    });
  }
  
  function doSelect(sql,args,f) {
    args = args || [];
    db.transaction(function(t){
      t.executeSql(sql,args,
      function(t,data){
        f(resultSetToHash(data));
      });
    },
    function(error){
      throw error;
    });
  }
  
  function doMultipleSelect(sqlArray,args,f) {
    args = args || [];
    var res = [];
    db.transaction(function(t){
      $.each(sqlArray,function(i,sql){
        t.executeSql(sql,args,
        function(t,data){
          res.push(resultSetToHash(data));
        })
      });
    },function(){
    },
    function(){
      f(res);
    });
  }
  
  function resultSetToHash(rs) {
    var res = [];
    var rows = rs.rows;
    for(var i=0;i<rows.length;i++) {
      res.push(rows.item(i));
    }
    return res;
  }
  
  var jQTouch = $.jQTouch({
      icon: 'roll.png',
      statusBar: 'black-translucent',
      startupScreen: 'startup.png',
      slideSelector: '#jqt > * > ul:not(.footer) li a,a.slide'    
  });
  
  updateCache();
  
  function getLista(f) {
    try {
      doSelect("SELECT idLavoro,titolo,descrizione as data,url FROM Lavori ORDER BY Lavori.data DESC",null,f);
    } catch(e) {
      console.log("getLista error "+e.message);
    }
  }
  
  function getLavoro(f) {
    try {
      doSelect("SELECT idLavoro,img,descrizione,ord FROM Immagini ORDER BY idLavoro, ord",null,f);
    } catch(e) {
      console.log("getLista error "+e.message);
    }    
  }
  
  function getGallery(f) {
    try {
      doSelect("SELECT img,descrizione FROM Gallery ORDER BY ord",null,f);
    } catch(e) {
      console.log("getGallery error "+e.message);
    }
  }
  
  
  var refreshScroll = function(page) {
    var scrollables = $(page).find("div.scrollable > *:first");
    scrollables.each(function(){
      var myiScroll = $(this).data("iScroll");
      if(myiScroll) {
        //rimuovo e reinserisco il wrapper della scrollbar perché rimane ad altezza 0
        $(myiScroll.wrapper).append($(myiScroll.scrollbars.y.wrapper).remove());
        $(myiScroll.wrapper).append($(myiScroll.scrollbars.y.jollyCorner).remove());
        myiScroll.refresh();
      }
    });  
  }

  var initScroll = function() {
    //blocca le azioni predefinite per evitare lo spostamento
    //del pagina sul tocco. Non richiamarlo sul touchstart
    //perché mi annulla tutte le zioni predefinte sui click
    //provo a metterlo sul touchmove
    $(document).bind("touchmove",function(e){
      console.log("touchmove prevented su document");
      e.preventDefault();
    });
    $('div.scrollable').children().each(function(){
      var myiScroll = new iScroll(this,"y");
      $(this).data("iScroll",myiScroll);
    });
    //riaggiorno scrollbar su cambio orientamento
    $("body").bind("turn",function(){
      $("div.current").each(function(){
        refreshScroll(this);
      });
    });
    $("#jqt").children().bind("pageAnimationEnd",function(e,data){
      if(data.direction=="out")
        return;
      refreshScroll(this);
    });
  }
  
  var initLavori = function(data) {
    var ul = $("#lavori").empty();
    var lavori = {};
    $.each(data,function(i,n){
        lavori[n.idLavoro] = {
          idLavoro: n.idLavoro,
          thumb: n.img,
          titolo : n.titolo,
          data: n.data,
          url: n.url
        };
    });
    var footer = $("#lavoro ul.footer"),
        visit = footer.find("li.visit a").click(function(){
          $(this).removeClass("active");
          return (window.confirm(this.href+"\nVuoi visitare questo sito?"));
        }),
        baloon = footer.find("li.detail div.detail_text"),
        pagination = footer.find("li.pagination ul");
    footer.find("li.detail a").tap(function(){
      if(baloon.is(":visible")) {
        $(this).removeClass("active");
        baloon.hide();
      } else {
        var immagini = $("#lavoro div.immagini"),
            pm = immagini.data("photoManager");
        var descr = immagini.find("li:eq("+pm.currentIndex+") .img_descrizione").html();
        $(this).addClass("active");
        baloon.html(descr).show();
      }
    });
    var jqObjects = {
      footer: footer,
      visit: visit,
      baloon: baloon,
      pagination: pagination
    }
    $.each(lavori,function(i,n){
      try{
        var li = $("#fragments #li_lavori li").clone();
        var a = li.find("a").html(n.titolo+" <span class=\"right\">"+n.data+"</span>");
        //utilizzare il metodo tap provoca il binding live dell'evento,
        //per cui utilizzo invece il binding semplice del tap
        n.jqObjects = jqObjects;
        a.bind($.support.touch?"tap":"click",n,lavoroClickHandler);
        ul.append(li);
      } catch(e) {console.log("errore lavori "+e)}
    })
  }
  
  var lavoroClickHandler = function(event) {
    var lavoro = $("#fragments #div_lavoro > div").clone();
    lavoro.find("h1").text(event.data.titolo);
    lavoro.find("h2").text(event.data.data);
    var width = $("#jqt").is(".landscape")?150:300;
    var ul = lavoro.find("ul").empty();
    var li_immagine = $("#fragments #li_immagini li");
    var dati_immagini;
    if(data_loaded.lavori)
      dati_immagini = $.map(data_loaded.lavori,function(el){
        return el.idLavoro!=event.data.idLavoro?null:el;
      });
    else {
      dati_immagini = [{img:"themes/roll/img/loader.gif"}];
      width = 32;
      var self = $(this);
      var refresh = function(){ 
        $(document).unbind("lavoriLoaded",refresh);
        if(window.location.hash=="#lavoro")
          self.triggerHandler($.support.touch?"tap":"click",event.data)
      } 
      $(document).bind("lavoriLoaded",refresh);
    }
    $.each(dati_immagini,function(j,immagine){
      var tmp_li = li_immagine.clone();
      tmp_li.find("img").attr("src",immagine.img).css("width",width+"px");
      tmp_li.find("div").html(immagine.descrizione);
      ul.append(tmp_li);
    });
    //inserisco pagina
    var img = $("#lavoro div.main").empty().append(lavoro).find("img");
    var divImmagini = $("#lavoro div.immagini"); 
    var jqObjects = event.data.jqObjects;
    jqObjects.visit.attr({target:"_blank",href:event.data.url});
    jqObjects.pagination.html("<li></li>");
    var pM;
    var bindPhotoManager = function(e,data) {
      if(data.direction=="out")
        return;
      pM = divImmagini.unbind("pageChange.photoManager").photoManager({width:($("#jqt").is(".landscape")?150:300)}).bind("pageChange.photoManager",function(e,data){
        jqObjects.pagination.find("a").removeClass("on").eq(data.index).addClass("on");
        var descr = divImmagini.find("li:eq("+pM.currentIndex+") .img_descrizione").html();
        jqObjects.baloon.html(descr);
      }).data("photoManager");
      if(pM.imgs.length>1) {
        var ml = (100-pM.imgs.length*15)/2;
        pM.imgs.each(function(i){
          var a = $("<a href=\"#\"><span>"+i+"</span></a>");
          var li = $("<li"+(i==0?" style=\"margin-left:"+ml+"px\"":"")+"></li>").append(a).appendTo(jqObjects.pagination);
        });
        jqObjects.pagination.find("a:first").addClass("on");
      }
    };
    $("#lavoro").unbind("pageAnimationEnd.lavoro").bind("pageAnimationEnd.lavoro",bindPhotoManager);
    $("body").unbind("turn.lavoro").bind("turn.lavoro",function(event,data){
      var w = data.orientation=="landscape"?150:300;
      img.css("width",w+"px");
      divImmagini.pm_refresh(w);
    });
    event.preventDefault();
    //poiché il contenuto è stato cancellato devo rilanciare lo scroll
    $('#lavoro div.scrollable > *').each(function(){
      var myiScroll = new iScroll(this,"y");
      $(this).data("iScroll",myiScroll);
    });
  }
  
  var initGallery = function(data) {
    var ul = $("#gallery .main ul").empty();
    var divImmagini = $("#gallery_zoom .main .immagini");
    var ul2 = divImmagini.find("ul").empty();
    var index = 0;
    var li_gallery = $("#fragments #li_gallery li");
    var li_gallery_foto = $("#fragments #li_gallery_foto li");
    var width = 320;
    $.each(data,function(i,foto){
      var li = li_gallery.clone();
      li.find("img").attr("src",foto.img);
      li.find("a").bind($.support.touch?"tap":"click",function(event){
        index = i;
      });
      li.appendTo(ul);
      var li2 = li_gallery_foto.clone();
      li2.find("img").attr("src",foto.img);
      li2.find("div.img_descrizione").html(foto.descrizione);
      li2.appendTo(ul2); 
    });
    var immagini = ul2.find("li");
    var pm = null;
    var updatePrevNext = function(index,total) {
      if(index==0)
        prev.addClass("off");
      else 
        prev.removeClass("off");
      if(index==total)
        next.addClass("off");
      else
        next.removeClass("off");
    }
    var footer = $("#gallery_zoom ul.footer");
    var prev = footer.find("a.prev").bind($.support.touch?"tap":"click",function(event){
      pm.previous();
      updatePrevNext(pm.currentIndex,pm.imgs.length-1);
      var descr = immagini.eq(pm.currentIndex).find("div.img_descrizione").html();
      baloon.html(descr);
      return false;
    });
    var next = footer.find("a.next").bind($.support.touch?"tap":"click",function(event){
      pm.next();
      updatePrevNext(pm.currentIndex,pm.imgs.length-1);
      var descr = immagini.eq(pm.currentIndex).find("div.img_descrizione").html();
      baloon.html(descr);
      return false;
    });
    var baloon = footer.find("li.detail div.detail_text");
    footer.find("li.detail a").bind($.support.touch?"tap":"click",function(){
      if(baloon.is(":visible")) {
        $(this).removeClass("active");
        baloon.hide();
      } else {
        var descr = immagini.eq(pm.currentIndex).find("div.img_descrizione").html();
        $(this).addClass("active");
        baloon.html(descr).show();
      }
    });
    var favourite = footer.find("li.fav a").bind($.support.touch?"tap":"click",function(){
      var img = divImmagini.find("li:eq("+pm.currentIndex+") img").attr("src");
      var body = $("<div>").append("<b>Allegato</b><img src=\""+img+"\" />");
      this.href = "mailto:?subject=RollUp%20immagine%20preferita&body="+encodeURIComponent(body.html());
      $(this).removeClass("active");
      return (window.confirm("Vuoi inviare per posta questa immagine?\n"));
    });    
    //console.log("gallery aggiunta");
    var bindPhotoManager = function() {
      if(data.direction=="out")
        return;
      if(!pm)
        pm = divImmagini.unbind("pageChange.photoManager").photoManager({width:width}).bind("pageChange.photoManager",function(){
            updatePrevNext(pm.currentIndex,pm.imgs.length-1);
            var descr = immagini.eq(pm.currentIndex).find("div.img_descrizione").html();
            baloon.html(descr);
        }).data("photoManager");
      pm.currentIndex = index;
      updatePrevNext(pm.currentIndex,pm.imgs.length-1);
      divImmagini.pm_refresh(width);
    };
    $("#gallery_zoom").unbind("pageAnimationEnd.lavoro").bind("pageAnimationEnd.lavoro",bindPhotoManager);
    //console.log("binding gallery aggiunto");
  }
  
  var initApp = function() {
    console.log("getLista");
    $(document).unbind("dataReady");
    getLista(function(data){
      console.log("init lavori");
      initLavori(data);
      $(document).bind("dataReady",function(){
        getLavoro(function(data){
          data_loaded.lavori = data;
          $(document).trigger("lavoriLoaded");
        });
        data_loaded.gallery = true;
        console.log("init gallery");
        getGallery(initGallery);
      });
      detectOnLine("Immagini,Gallery");
      if(!page) {
        jQTouch.goTo((!window.navigator.standalone?"#standalone":"#home"));
        $("#jqt div.toolbar a.refresh").bind($.support.touch?"tap":"click",function() {
          page = window.location.hash;
          jQTouch.goTo("#aggiornamento");
          $(document).bind("dataReady",initApp);
          detectOnLine(); 
        });
        initScroll();
        $("#contact_detail a[href^=mailto:]").click(function(){
          var addr = this.href.split(/mailto:/)[1];
          return (window.confirm(addr+"\nVuoi inviare una email a questo indirizzo?\n"));
        });
      } else
        jQTouch.goTo(page);
    });  
  }
  
  //Per l'aggiornamento:
  //array di tipologie di dati caricati
  //all'inizio carico solo lavori
  //ogni volta che vedo un'item,
  //verifico se ho caricato i dati
  //se si procedo normalmente,
  //se no procedo al carcamento json e poi al resto
  var data_loaded = {
    lavori : false,
    gallery: false
  }
  
  var page = "";
  $(function(){
    console.log("dom ready");
    if(bootDbLoaded)
      initApp();
    else
      $(document).bind("dataReady",initApp);
  })
})(jQuery);
