var Offline = (function(){
    var workerPool;
    var db;
    var prevProgress = 0;
    var workers = [ {storeName: 'webreader.dynamic',
    					   type:'dynamic',
                           total: 0,
                           captured: 0,
                           workerId: -1,
                           status: 'online'},
                          {
                           storeName: 'webreader.static',
                           type: 'static',
                           total: 0,
                           captured: 0,
                           workerId: -1,
                           status: 'online'},
                          {
                           storeName: 'webreader.static',
                           type: 'static',
                           total: 0,
                           captured: 0,
                           workerId: -1,
                           status: 'online'}
                           ];
    
    var start;
    var offlineSettings = {};
    var ajaxError = false;
    
    /* Google gears functions */
    function isGoogleGearsInstalled() {
        return window.google && window.google.gears
    }
  
    function initGoogleGears(){
        var ret = true;
        if (!isGoogleGearsInstalled()) {
            $("#button_link_download").trigger("click");
            ret = false;
        }else {
            try{ 
                initDB();
            } catch(e) {
                // in case user denies
                ret = false;
            }
        }
        return ret;
    }
    
    /* Workers management functions */
    function initWorkers(){

        if(!workerPool){
            workerPool = google.gears.factory.create('beta.workerpool');
            workerPool.onmessage = function(a, b, message) {
                var status = message.body.status;
                var sender = message.sender;
 
                if( status == 'urls') {
                    if(message.body.detail.indexOf('capture') == 0){
                        incrementWorkerCaptured(sender); 
                        updateProgress();
                    }else if (message.body.detail.indexOf('total:') == 0){
                        var total = parseInt(message.body.detail.substring(6, message.body.detail.indexOf(' ', 6)));
                        addWorkerTotal(sender, total); 
                    }

                }else if ( status == 'completed') {
                	setWorkerStatus(sender, 'ready');
                    updateProgress();
                }
                log(sender,  message.body); 
            };
        }
    }

    function addWorkerTotal(workerId, total){
    	for(var i = 0; i < workers.length; i++){
    		if(workers[i].workerId == workerId){
    			workers[i].total += total;
    			break;
    		}
    	}
    }
    
    function incrementWorkerCaptured(workerId){
    	for(var i = 0; i < workers.length; i++){
    		if(workers[i].workerId == workerId){
    			workers[i].captured++;
    			break;
    		}
    	}
    }

    function setWorkerStatus(workerId, status){
    	for(var i = 0; i < workers.length; i++){
    		if(workers[i].workerId == workerId){
    			workers[i].status = status;
    			if(status == 'ready'){
    				workers[i].captured = workers[i].total; 
    			}
    			break;
    		}
    	}
    }
    
    function sendMessage(recipient, command, content){ 
        var msg = {command:command};
        if(typeof content != 'undefined' )
            msg.content = content;
        workerPool.sendMessage(msg, recipient);       
    }
    
    function getTotal() {
        var total = 0;
        for(var i = 0; i < workers.length; i++) {
           total += workers[i].total;
        }
        return total;
    }

    function getCompleted() {
        var completed = 0;
        for(var i = 0; i < workers.length; i++) {
           completed += workers[i].captured;
        }
        return completed;
    }
    
    function captureUrls(workerId, urls){
    	sendMessage(workerId, 'getUrls', {urls:urls, update:offlineSettings.version_updated});
    }
    
    /* Google Database functions */ 
    function initDB(){
        if(!db)
            db = google.gears.factory.create('beta.database');        
    }

    function installDB() {

        initDB();
        db.open();
        db.execute('create table if not exists collection (url text primary key, desktop_shortcut text)');
            
        db.execute('create table if not exists document (url text primary key, collection_id integer, title text, publish_date text, static_domain text, dynamic_domain text, zoom_level integer, zoom_in_level integer, page_mode integer, u1 text, version text )');
        var rs = db.execute('select name from sqlite_master where type = "table" and name="search_text"');
        if(!rs.isValidRow())
            db.execute('create virtual table search_text using fts2 (text)');
        
        db.execute('create table if not exists search_page (document_id integer, page_number integer, title text, thumbnail text)');
        db.execute('create table if not exists search_word (page_id integer, word text, x integer, y integer, w integer, h integer)');
        rs.close();
        db.close();
        
    }
        
    function insertPage(page) {
    	
    	var rs = db.execute('select rowid from search_page where document_id = ? and page_number = ?', [offlineSettings.document_id, page.pageNumber]);
    	if(!rs.isValidRow()){
    		// is not existing
            db.execute('begin transaction');
    		db.execute('insert into search_text(text) values (?)', [page.text]);
    		var page_id = db.lastInsertRowId;
    		db.execute('insert into search_page (rowid, document_id, page_number, title, thumbnail) values( ?, ?, ?, ?, ? )', 
    				   [db.lastInsertRowId, offlineSettings.document_id, page.pageNumber, page.title, page.thumbnailUrl]);
            if(page.searchWord != undefined ){
    		    insertWords(page_id, page.searchWord);
            }
            db.execute('commit transaction');
    	}
        rs.close();
    }

    function insertWords(page_id, words){
    	
    	for(var i=0; i < words.length; i++){
    		db.execute('insert into search_word values (?, ?, ?, ?, ?, ?)', 
    				[page_id,
    				 words[i].word,
    				 words[i].x,
    				 words[i].y,
    				 words[i].w,
    				 words[i].h]);
    	}
    }

    function getOfflineSettings(documentUrl){
		initDB();
        db.open();
        var settings = {}; 
        try { 

            var rs = db.execute('select d.rowid, d.static_domain, d.dynamic_domain, d.zoom_level, d.zoom_in_level, d.page_mode, d.u1, d.version, c.desktop_shortcut from document d, collection c where d.collection_id = c.rowid and d.url = ?', 
                [documentUrl]);
        
            if(rs.isValidRow()){
        	    settings.document_id = rs.field(0);
        	    settings.url = DocumentProperties.getDocumentUrl();
        	    settings.static_domain = rs.field(1);
        	    settings.dynamic_domain = rs.field(2);
        	    settings.z = rs.field(3);
        	    settings.zin = rs.field(4);
        	    settings.pm = rs.field(5);
        	    settings.u1 = rs.field(6);
        	    settings.version = rs.field(7);
                settings.desktop_shortcut = (rs.field(8) == 'yes')? true: false;
                rs.close();
            }
        }catch(ex) {
           //ignore 
        } 
        db.close();
        return settings;
    }
    
    function setOfflineSettings() {
    	
    	// set the current setting with 
        offlineSettings.document_id = null;
    	offlineSettings.url = DocumentProperties.getDocumentUrl();
    	offlineSettings.static_domain = DocumentProperties.getStaticDomain();
    	offlineSettings.dynamic_domain = getDomain();
    	offlineSettings.z = PageModel.zoomLevel;
    	offlineSettings.zin = PageModel.getZoomInLevel();
    	offlineSettings.pm = PageModel.pageMode;
    	offlineSettings.u1 = PageModel.u1;
        offlineSettings.collection_url = DocumentProperties.getCollectionUrl();    	
    	initDB();
    	db.open();
        
        var rs = db.execute("select rowid, desktop_shortcut from collection where url = ? ", [offlineSettings.collection_url]);
        if(rs.isValidRow()){
            offlineSettings.collection_id = rs.field(0);
            offlineSettings.desktop_shortcut = rs.field(1) == "yes" ? true: false;
        } else {
            db.execute("insert into collection values (?, ?)", [offlineSettings.collection_url, "no" ]);
            offlineSettings.collection_id = db.lastInsertRowId;
        }
        rs.close();

         
    	rs = db.execute('select rowid, version from document where url=?', [offlineSettings.url]);
        if(rs.isValidRow()){
        	offlineSettings.document_id = rs.field(0);
        	offlineSettings.version = rs.field(1);
        	db.execute('update document set static_domain = ?, zoom_level = ?, zoom_in_level = ?, page_mode = ?, u1 = ? where rowid = ?', 
                            [
                            offlineSettings.static_domain,
                            offlineSettings.z,
                            offlineSettings.zin,
                            offlineSettings.pm,
                            offlineSettings.u1,
                            offlineSettings.document_id
                             ]);
        	offlineSettings.new_doc = false;
            rs.close();
        }else {
        	db.execute('insert into document(url, title, publish_date, static_domain, dynamic_domain, zoom_level, zoom_in_level, page_mode, u1, collection_id) values(?,?,?,?,?,?,?, ?,?,?)', 
                            [
                            offlineSettings.url,
                            DocumentProperties.getTitle(),
                            DocumentProperties.getPublishDate(),
                            offlineSettings.static_domain,
                            offlineSettings.dynamic_domain,
                            offlineSettings.z,
                            offlineSettings.zin,
                            offlineSettings.pm,
                            offlineSettings.u1,
                            offlineSettings.collection_id
                             ]);
        	offlineSettings.document_id = db.lastInsertRowId;
        	offlineSettings.new_doc = true;
            rs.close();
        }

        db.close();
    }

    function checkVersionUpdate(version){
    	
    	if(!offlineSettings.update_version){
        	if(version != offlineSettings.version) {
	        
        		offlineSettings.version = version;
        		// update the version in the database 
        		// offlineSettings.version_updated will be reset to false when going offline
        		offlineSettings.version_updated = true;
        		
        		initDB();
        		db.open();
        		db.execute("update document set version = ? where rowid = ?",
        				[version, offlineSettings.document_id]);
        		db.close();
	        } 
        } 
    }

    /**
     * process offline functions 
     */
    function generateOfflineSearchDB() {
        
    	installDB();
    	setOfflineSettings();
    	
        if(offlineSettings.new_doc){
	        for(var i = 1; i <= PageModel.lastPage; i += 50){        
  	        if(ajaxError===true){
                return;
            }
	    	    var searchJson = "search_" + padLeft(""+i, 4, '0') + ".json";
	    	    getJSON( offlineSettings.url + "/data/offline/" + searchJson, processSearch);
	        }
	    }
    }

    function generateOfflineStores(){
    	
        if(ajaxError===true){
            return;
        }    	
        initWorkers();
    	
        prevProgress = 0;
        for (var i = 0; i < workers.length; i++) { 
        	workers[i].total = 0;
        	workers[i].captured = 0;
            if(workers[i].workerId < 0){ 

                if(workers[i].type == 'dynamic')
                    workers[i].domain = offlineSettings.dynamic_domain;
                else
                    workers[i].domain = offlineSettings.static_domain;
        
                workers[i].workerId = workerPool.createWorkerFromUrl(workers[i].domain + '/javascript/offline/cache-worker.js');
                sendMessage(workers[i].workerId, 'openStore', workers[i].storeName);
                //sendMessage(workers[i].workerId, 'domain', workers[i].domain);    
            }
           
        }
        var d = new Date();
        start = d.getTime();
        
        // get dynamic urls
        getJSON( offlineSettings.url + "/data/offline/dynamic_manifest.json", processDynamicManifest);
        
        // get the static content
        getJSON( offlineSettings.url + "/data/offline/static_manifest.json", processStaticManifest1);
        getJSON( offlineSettings.url + "/data/offline/static_manifest_" + offlineSettings.z + ".json", processStaticManifest1);
        getJSON( offlineSettings.url + "/data/offline/static_manifest_" + offlineSettings.zin + ".json", processStaticManifest2);
        
        Offline.timerId = window.setInterval( function() {
            var done = true;
            for(var i=0; i < workers.length; i++){
            	if(workers[i].status != 'ready') {
            		done = false;
            		break;
            	}
            }
            
            if(done && ajaxError===false){
                window.clearInterval(Offline.timerId);
                setOffline();
                downloadComplete(getTotal());
                getOfflineIndicator();
                Navbar.View.goOffline();
                Console.log("The document is now available offline!!!\n");
                var d = new Date();
                var end = d.getTime();
                end = end - start;
                end = end / 1000;
                Console.log('total urls: ' + getTotal() + ' completed in ' + end + ' seconds');
                if(CookieManager.get("shouldCreateShortcut")){ 
                    createShortcut();
                }
            }

        }, 1000);
    }
    
    function getParameterString(pm, z, u1, numPagesViewed){
    	var ret = "pm=" + pm + "&z=" + z;
    	if(numPagesViewed)
    		ret += "&numPagesViewed=-1";
    	if(u1)
    		ret += "&u1=" + u1;
    	return ret;
    }

    function getCurrentDocumentPageUrl(pn){
        
        return	getDocumentPageUrlWithHash(offlineSettings.url,
                                    pn,
                                    offlineSettings.pm, 
                                    offlineSettings.z, 
                                    offlineSettings.u1, 
                                    true);
    }

    function getDocumentPageUrlWithHash(documentUrl, pn, pm, z, u1, escapeHash){
        var page = "#pg" + pn;
        if(escapeHash)
            page=escape(page);
        return	documentUrl + "?" + getParameterString(pm, z, u1) + page;
    }

    function processDynamicManifest(data){
    
      if(ajaxError===true){
          return;
      }
    	var urls = new Array();
    	var i = 0;
    	
    	// check Version
    	checkVersionUpdate(data.version);

        // create the landing page
        urls.push(offlineSettings.url + "?" + getParameterString(offlineSettings.pm, offlineSettings.z, offlineSettings.u1));	
    	// create #pgN 
        for(i=1; i<= PageModel.lastPage; i++){
    		urls.push(getCurrentDocumentPageUrl(i));
    	}
       
    	for(i=0; i< data.entries.length; i++){
    		var url = data.entries[i].url;
    			
    		if(url.indexOf('Page.action?') > 0){
    			urls.push(url + "&" + getParameterString(offlineSettings.pm, offlineSettings.z, offlineSettings.u1));
    			urls.push(url + "&" + getParameterString(offlineSettings.pm, offlineSettings.zin, offlineSettings.u1));
    		} else if (url.indexOf('Popup.action?') > 0){
    			urls.push(url + "&" + getParameterString(offlineSettings.pm, offlineSettings.z, offlineSettings.u1, true));
    			urls.push(url + "&" + getParameterString(offlineSettings.pm, offlineSettings.zin, offlineSettings.u1, true));
    		} else if(url.indexOf("?pm=") > 0){
    			var temp = url.substring(0, url.indexOf("?pm="));
    			urls.push(temp + "?pm=" + offlineSettings.pm);
    		} else {
    			urls.push(url);
            }
    	}
    	// put all the offline template call url links here
    	urls.push(offlineSettings.dynamic_domain + offlineSettings.collection_url + "/Offline.action");
    	urls.push(offlineSettings.dynamic_domain + offlineSettings.url + "/FreeMarker.action?template=offline/offline_indicator");
    	urls.push(offlineSettings.dynamic_domain + offlineSettings.url  + "/FreeMarker.action?template=offline/offline_welcome");
    	urls.push(offlineSettings.dynamic_domain + offlineSettings.url + "/FreeMarker.action?template=offline/offline_reactivated");
    	urls.push(offlineSettings.dynamic_domain + offlineSettings.url + "/FreeMarker.action?template=offline/offline_back_online");
    	
        captureUrls(workers[0].workerId, urls);
    }

    
    function processStaticManifest1(data){
      if(ajaxError===true){
          return;
      }    	
    	// check Version
    	checkVersionUpdate(data.version);
    	
    	var urls = new Array();
        for(var i=0; i < data.entries.length; i++) {
            urls.push(data.entries[i].url);
        }	
    	captureUrls(workers[1].workerId, urls);
    }

    function processStaticManifest2(data){
      if(ajaxError===true){
          return;
      }    	
    	var urls = new Array();
        for(var i=0; i < data.entries.length; i++) {
            urls.push(data.entries[i].url);
        }	
    	captureUrls(workers[2].workerId, urls);
    }

    function processSearch(data){
      if(ajaxError===true){
          return;
      }
        db.open();
    	var pages = data.searchPageList.searchPage;
    	for(var i=0; i < pages.length; i++ ){
    		insertPage(pages[i]);
    	}
    	
    	delete data;
        db.close();
    }
    
    /**
     * search function  
     */
    function search(words, searchAny){
        
        initDB();
        db.open();    
        var matchwords;
        if(searchAny)
            matchwords = words.split(" ").join(" OR ");
        else
            matchwords = words;
            
        var query = "select d.url, d.zoom_level, d.page_mode, p.page_number, p.title, p.thumbnail, snippet(search_text, '<span class=\"highlight\">', '</span>'),";
        query += " offsets(search_text), ";
        query += "d.u1";
        query += " from search_text t, search_page p, document d ";
        query += " where t.rowid = p.rowid and d.rowid = p.document_id and search_text match ? ";

        Console.log("query: " + query + "\n match=" + matchwords);
        var rs = db.execute(query, [matchwords]);
        var results = [];
        while(rs.isValidRow()){
            var result = new SearchResult(rs);
            results.push(result);
            rs.next();
        }       
        rs.close();    
        db.close();
        return results.sort(sortSearchResult);
    }

    function sortSearchResult(a,b){

        /* compare order: termMatch desc, matchCount desc, pageNumber asc*/
        if(a.termMatch > b.termMatch) return -1;
        else if (a.termMatch < b.termMatch ) return 1;
        else {
            if(a.matchCount > b.matchCount) return  -1;
            else if (a.matchCount < b.matchCount) return 1;
            else {
                return a.pageNumber - b.pageNumber; 
            }
        }
    } 

    function searchHighlights(words, pg, pm, z){
        db.open();
        var query="select w.x, w.y, w.w, w.h from search_word w, search_page p where w.page_id = p.rowid and p.document_id = ? and p.page_number = ? and (";
        $.each(words.split(' '), function(i, word){
            if(i > 0)
                query += " OR ";
            query += "lower(w.word) like '" + word.toLowerCase() + "%'";
        });
        query += ")";
        Console.log("search hight query: " + query);
        var rs = db.execute(query, [offlineSettings.document_id, pg]);
        var highlights = [];

        while(rs.isValidRow()){
            var hl = {};
            hl.x = Math.round(rs.field(0) * z / 100);
            hl.y = Math.round(rs.field(1) * z / 100);
            hl.w = Math.round(rs.field(2) * z / 100);
            hl.h = Math.round(rs.field(3) * z / 100);
            highlights.push(hl);
            rs.next();
        }

        rs.close();
        db.close();
        return highlights;
    }
    
    function createShortcut() {
	  var desktop = google.gears.factory.create("beta.desktop");
	  var description = "This shortcut launches the " + DocumentProperties.getCollectionTitle() + " offline";

	  var icons = {
	    "32x32": DocumentProperties.getDesktopShortcutIcon()
	   };

	  desktop.createShortcut(DocumentProperties.getCollectionTitle(),  // name
	                         offlineSettings.dynamic_domain + offlineSettings.collection_url + "/Offline.action",  // url
	                         icons,  // icons (must specify at least one)
	                         description);  // description (optional)
      offlineSettings.desktop_shortcut = true;
      db.open();
      db.execute("update collection set desktop_shortcut = ? where rowid = ? ", ["yes", offlineSettings.collection_id]);
      db.close(); 
      CookieManager.remove("shouldCreateShortcut");
	}

    
    /* utilities functions */ 
    function getJSON(href,success,error){
        opts = {};
        opts.url = href;
        opts.type = "GET";
        opts.dataType = "json";
        if(success && typeof success == "function"){
            opts.success = success;
        }
        if(error && typeof error == "function"){
            opts.error = error;
        }else{
            opts.error = handleAjaxError;
        }
        $.ajax(opts);
    }
    
    function handleAjaxError(){
        ajaxError = true;
        $("#offline_progress_dialog").dialog("close");
        window.clearInterval(Offline.timerId);
        Offline.goOnline();
        ViewHelper.dataSwitchError();
    }
    
    function log(sender, message){
        //Console.log("sender=" + sender + " " +  message.status + ":" + message.detail);
    }
    
    function getDomain(){
    	var domain = location.href;
        var pos = domain.indexOf('/',8);
        domain = domain.substring(0,pos);
        return domain;
    }

    function getCollectionUrl(){
        if(!offlineSettings.collection_url){
    	    var url = location.href;
            var pos = url.indexOf('/', 8);
            offlineSettings.collection_url =  url.substring(pos, url.indexOf('/', pos+1));
        }
        return offlineSettings.collection_url;
    }

    function padLeft(value, length, pad){
    	var ret = value;
    	while(ret.length < length){
    		ret = pad + ret;
    	}
    	
    	return ret;
    }

    function sendMessage(recipient, command, content){ 
        var msg = {command:command};
        if(typeof content != 'undefined' ){
            msg.content = content;
        }
        if(workerPool){
            workerPool.sendMessage(msg, recipient);
        }
    }
    function getTotal() {
        var total = 0;
        for(var i = 0; i < workers.length; i++) {
           total += workers[i].total;
        }
        return total;
    }
    function getCompleted() {
        var completed = 0;
        for(var i = 0; i < workers.length; i++) {
           completed += workers[i].captured;
        }
        return completed;
    }
    
    function updateProgress() {
        var total = getTotal();
        var completed = getCompleted();
        var progress_visible = false;
        if(ajaxError===true){
            $("#offline_progress_dialog").dialog("close");
        }else if(total > 0){
            var progress = Math.floor((completed * 100 )/ total);
            if(progress_visible===false && $("#downloading").is(".hidden")){
                $("#checking").addClass("hidden");
                $("#downloading").removeClass("hidden");
                progress_visible = true;
            }
            if(progress > prevProgress) {
                $("#offline_progress").progressbar('value',progress);
                $("#percent_complete").text(progress);
                prevProgress = progress;
            }
        }
    }
    
    function downloadComplete(total){
        var download_overlay = $("#offline_progress_dialog").parents(".ui-dialog");
        var download_content = $("#offline_progress_content");
        var wh = $(window).height();
        var ww = $(window).width();
        var div_h = download_overlay.height();
        var div_w = download_overlay.width();
        var new_top = (wh/2) - (div_h/2);
        var new_left = (ww/2) - (div_w/2);
        var doc_url = offlineSettings.url;
        var dialog_template = total > 0 ? "download_complete" : "offline_reactivated";
        
        Offline.downloadInProgress = false;
        download_content.load(
            doc_url+"/FreeMarker.action?template=offline/"+dialog_template,
            function(){
                $(this).animate({height:130});
                $("#close_dialog",$(this)).bind('click',function(){
                    var to = $("#button_link_offline_options").offset();
                    var from = download_overlay.offset();
                    
                    download_overlay
                        .animate({left:(from.left*2)},{queue:true,duration:150},"linear")
                        .animate({left:(from.left*2+(to.left-from.left*2))},{queue:true,duration:250},"linear")
                        .animate({left:to.left,opacity:.5},{queue:true,duration:300},"linear")
                        .animate({opacity:0},{queue:true,duration:200});
                    
                    download_overlay.animate(
                        {top:0,height:31,width:97},
                        {queue:false,duration:1000,easing:"easeOutQuint",complete:function(){
                            $("#offline_progress_dialog").dialog("close");
                        }}
                    );
                    
                    download_content.animate({opacity:0},750);
                    
                });
            }
        );
        download_overlay.animate(
            {top: new_top, left: new_left, height: 300 },
            "slow",
            function(){
                setTimeout(function(){
                    $("#close_dialog",download_overlay).trigger('click');
                },12000);
            }
        );
    }
    
    function getOfflineIndicator(){
        var doc_url = offlineSettings.url;
        DataSwitch.get({ 
            url: doc_url+"/FreeMarker.action?template=offline/offline_indicator",
            success: function(indicator_html){
                $(indicator_html).insertBefore("#button_link_help");
            }
        });
    }
    
    function getBackOnlineDialog(){
        var doc_url = DocumentProperties.getDocumentUrl();
        DataSwitch.get({ 
            url: doc_url+"/FreeMarker.action?template=offline/offline_back_online",
            success: function(dialog_html){
                $(ViewHelper.shadowWrap(dialog_html,"black","offline_back_online_dialog"))
                .appendTo("body")
                .dialog({
                    width:300,
                    modal:false,
                    resizable:false,
                    draggable:false,
                    close: function(e,ui){
                        delete PageElements.dialogs['offline_back_online'];
                        $(this).dialog('destroy').remove();
                    },
                    open: function(e,ui){
                        var that = $(this);
                        $("#enable_online",that).bind('click',function(){
                            $("#offline_back_online_dialog").dialog("close");
                        });
                        PageElements.dialogs["offline_back_online"] = {
                            'id':'offline_back_online_dialog',
                            'link_active':true,
                            'dialog_active':true
                        };
                        setTimeout(function(){
                            $("#offline_back_online_dialog").parents(".ui-dialog").fadeOut("slow",function(){
                                $("#offline_back_online_dialog").dialog("close");
                            });
                        },5000);
                    }
                });           
            }
        });    
    }
    
    function getOfflineWelcomeDialog(){
        var doc_url = DocumentProperties.getDocumentUrl();
        DataSwitch.get({ 
            url: doc_url+"/FreeMarker.action?template=offline/offline_welcome",
            success: function(welcome_html){
                $(ViewHelper.shadowWrap(welcome_html,"black","offline_welcome_dialog"))
                .appendTo("body")
                .dialog({
                    width:450,
                    modal:false,
                    resizable:false,
                    draggable:false,
                    close: function(e,ui){
                        delete PageElements.dialogs['offline_welcome'];
                        $(this).dialog('destroy').remove();
                    },
                    open: function(e,ui){
                        var that = $(this);
                        $("#continue_offline",that).bind('click',function(){
                            $("#offline_welcome_dialog").dialog("close");
                        });
                        $("#enable_online",that).bind('click',function(){
                            $("#offline_welcome_dialog").dialog("close");
                            Offline.goOnline();
                            getBackOnlineDialog();
                        });
                        PageElements.dialogs["offline_welcome"] = {
                            'id':'offline_welcome_dialog',
                            'link_active':true,
                            'dialog_active':true
                        };
                    }
                });
            }
        });
    }
    
    function downloadStart() {
        var doc_url = DocumentProperties.getDocumentUrl();
        if($("input.install_shortcut:checked",$("#button_link_download_dialog")).length > 0){
            CookieManager.set("shouldCreateShortcut","true");
        }
        ViewHelper.closeAllDialogs();
        $("#zoom_wrapper",Navbar.Model.navbar).hide();
        DataSwitch.get({ 
            url: doc_url+"/FreeMarker.action?template=offline/offline_progress",
            success: function(progress_html){
                $(ViewHelper.shadowWrap(progress_html,"black","offline_progress_dialog"))
                    .appendTo("body")
                    .dialog({
                        position:[$(window).width() - 350,40],
                        closeOnEscape: false,
                        modal:false,
                        resizable:false,
                        draggable:false,
                        close: function(e,ui){
                            var that = $(this);
                            ViewHelper.setDialogModalOverride(false);
                            that.fadeOut("slow",function(){
                                delete PageElements.dialogs['offline_progress'];
                                that.dialog('destroy').remove();
                            });
                        },
                        open: function(e,ui){
                            var that = $(this);
                            if(ajaxError===true){
                                that.dialog("close");
                            }else{
                                if(!/MSIE 6.0/.test(navigator.userAgent)){
                                    that.parent().css("position","fixed");
                                }
                                ViewHelper.setDialogModalOverride(true);
                                ViewHelper.removeDialogCloseButton(that);
                                $("#offline_progress",that).progressbar();
                                PageElements.dialogs["offline_progress"] = {
                                    'id':'offline_progress_dialog',
                                    'link_active':true,
                                    'dialog_active':true
                                };
                            }
                    }
                });
            }
        });
    }
    
    function getDocumentThumbnails(){
    	initDB();
    	db.open();
    	var docs = [];
    	var rs = db.execute("select d.dynamic_domain, d.static_domain, d.url, d.title, d.publish_date, d.page_mode, d.zoom_level, d.u1 from document d, collection c where d.collection_id = c.rowid and c.url = ? order by d.publish_date desc", [getCollectionUrl()]);
    	while(rs.isValidRow()){
    		var url = rs.field(0) + rs.field(2) + "?" + getParameterString(rs.field(5), rs.field(6), rs.field(7));
    		docs.push({url:url,
    				   img:rs.field(1) + rs.field(2) + "/cover.gif",
    				   title:rs.field(3)
    				   });
    		rs.next();
    	}
    	rs.close();
    	db.close();
    	
    	var html = "";
    	
    	$.each(docs, function(i, doc){
    		html += "<div class=\"thumb\"><a href=\"" + doc.url + "\">";
    		html += "<img border=\"0\" alt=\"" + doc.title + "\" src=\"" + doc.img + "\"/>";
    		html += "<span>" + doc.title + "</span>";
    		html += "</a></div>"
    		
    	})
    	
    	return html;
    }

    function setOffline() {
        prevProgress = 0;
        offlineSettings.version_updated = false;
        offlineSettings.new_doc = false;
        CookieManager.set("offline", "true");
    }

    function setOnline() {
        CookieManager.remove("offline");
        CookieManager.remove("shouldCreateShortcut");
        offlineSettings.version_updated = false;
        offlineSettings.new_doc = false;
        delete Offline.offlineCookie;
        prevProgress = 0;
    }
   
    /** public functions */ 
    return {
        timerId: null,
        downloadInProgress: false,
        isOffline: function() {
            if(typeof Offline.offlineCookie == "undefined"){
                Offline.offlineCookie = CookieManager.get("offline");
            }
            if(Offline.offlineCookie && isGoogleGearsInstalled()!==false){
                return true;
            }
            return false;
        },
        
        init: function(){
        	offlineSettings.new_doc = false;
        	offlineSettings.version_updated = false;
        	  this.loadOfflineSettings();
            if(this.isOffline() && typeof google != "undefined" && google.gears.factory.hasPermission===true){
                if(!offlineSettings.document_id) {
                    Offline.goOnline();
                }else {
                    getOfflineIndicator();
                    getOfflineWelcomeDialog();
                    Navbar.View.goOffline();
                }
            }else if(CookieManager.get("download")){
                var autoDownload = setInterval(function(){
                    if(Drawer.View.firstTabLoaded===true){
                        clearInterval(autoDownload);
                        CookieManager.remove("download");
                        Offline.goOffline();
                    }
                },500);
            }else if(Offline.offlineCookie){
                CookieManager.remove("offline");
                delete Offline.offlineCookie;
            }
        },
        goOffline: function(){  
        	 if (!Offline.isOffline()){
            	if (initGoogleGears()){
            		  Offline.downloadInProgress = true;
                  PageView.setAutoZoom(false);
                	downloadStart();
                	generateOfflineSearchDB();
                  generateOfflineStores();
                }else{
                	document.location.reload(true);
                }
            } else {
       				setOffline();
            } 
       },
        
        goOnline: function(){
        	$("#button_link_offline_options").remove();
            $("#button_link_offline_options_dialog").dialog("close");
            Navbar.View.goOnline();
            setOnline();
        },
        goBackOnline: function(){
        	Offline.goOnline();
            Navbar.View.goOnline();
            getBackOnlineDialog();
           
        },
        getSearchResults: function(words, searchAny){
            return search(words, searchAny); 
        },

        getSearchHighlights: function(words, pg, pm, z) {
            return searchHighlights($.trim(words), pg, pm, z);
        },

        loadDocuments: function() {
        	return getDocumentThumbnails();
        },
        
        getOfflineSettings: function() {
        	return offlineSettings;
        },
        getZoomLevel: function() {
            return offlineSettings.z;
        },
        getZoomInLevel: function() {
            return offlineSettings.zin;
        },
        getDocumentPageUrl: function(documentUrl, pn, pm, z, u1){
            return  getDocumentPageUrlWithHash(documentUrl, pn, pm, z, u1, false);
        },
        loadOfflineSettings : function(){
           if(isGoogleGearsInstalled() && google.gears.factory.hasPermission===true){
               offlineSettings = getOfflineSettings(DocumentProperties.getDocumentUrl());
               //DT-4590: Changing text when 'offline' has already been downloaded.
               if (offlineSettings != null) {
               		$("#start_download_installed_text p strong").text(DocumentProperties.getLanguageText().navbar.download.offline.start_download_installed_text);
               		$("#download_offline_text").html(DocumentProperties.getLanguageText().navbar.download.offline.download_offline_text);
               		$("#download_message_text").hide();
               	}
           }
        }
    }
})();


