// create the console object so that we don't break IE
if (!("console" in window)) {
    window.console = {
        log: function(s) {}
    };
}

window.peekeez = {};

window.peekeez.util = (function() {
    function makeFlashObject(name,ver,width,height,bgcolor,params) {
        var codebase, pluginspage;
                
        if (window.location.protocol.toString() == "https:") {
            codebase = 'https://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0';
            pluginspage = 'https://get.adobe.com/flashplayer/';
        } else {
            codebase = 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0';
            pluginspage = 'http://get.adobe.com/flashplayer/';
        }
        
        return AC_FL_RunContent(
        		'codebase', codebase,
        		'height', height,
        		'width', width,
        		'src', '/flash/' + name + '?ver=' + ver,
        		'movie', '/flash/' + name + '?ver=' + ver,
        		'quality', 'high',
        		'pluginspage', pluginspage,
        		'align', 'middle',
        		'play', 'true',
        		'loop', 'true',
        		'scale', 'showall',
        		'wmode', 'window',
        		'devicefont', 'false',
        		'id', name,
        		'bgcolor', bgcolor,
        		'name', name,
        		'menu', 'true',
        		'allowFullScreen', 'true',
        		'allowScriptAccess','sameDomain',
        		'salign', '',
        		'FlashVars', params); 
    }
    
    function handleHtmlUpdateResponse(request,container,callback) {
        if (request.readyState == 4 && request.status == 200) {
            var responseHtml = request.responseText ? request.responseText : null;
            $(container).update(responseHtml);
            if (callback)
                callback();
        }
    }

    function handleJsonResponse(request,callback) {
        //console.log("In handleJsonResponse. state = " + request.readyState);
        if (request.readyState == 4 && request.status == 200) {
            //console.log("JSON text is " + request.responseText);
            try {
                var responseData = request.responseText ? eval('(' + request.responseText + ')') : null;
                callback(responseData);
            } catch (e) {
                //console.log("Error evaluating JSON return");
                callback(null);
            }
        }
    }
    
    return {
        makeFlashObject: makeFlashObject,

        htmlUpdateRequest: function(uri, container, callback) {
            //uri += ((uri.indexOf('?') == -1) ? '?' : '&') + "version=" + new Date().valueOf().toString();
            
            var request = null;
            if (window.XMLHttpRequest) { 
                // Mozilla, Safari,...
                request = new XMLHttpRequest();
            } else if (window.ActiveXObject) { 
                // IE
                try {
                    request = new ActiveXObject("Msxml2.XMLHTTP");
                } catch (e) {
                    try {
                        request = new ActiveXObject("Microsoft.XMLHTTP");
                    } catch (e) {}
                }
            }
            
            if (!request) {
                alert('Cannot create an XMLHTTP instance');
                return false;
            }

            request.onreadystatechange = handleHtmlUpdateResponse.bind(this,request,container,callback);
            request.open("GET", uri, true);
            request.send(null);
            return request;
        },

        jsonRequest: function(uri, callback, options) {
            uri += ((uri.indexOf('?') == -1) ? '?' : '&') + "version=" + new Date().valueOf().toString();
            
            var method = "GET";
            var request = null;
            
            if (options && "method" in options)
                method = options.method;
                
            if (window.XMLHttpRequest) { 
                // Mozilla, Safari,...
                request = new XMLHttpRequest();
            } else if (window.ActiveXObject) { 
                // IE
                try {
                    request = new ActiveXObject("Msxml2.XMLHTTP");
                } catch (e) {
                    try {
                        request = new ActiveXObject("Microsoft.XMLHTTP");
                    } catch (e) {}
                }
            }
            
            if (!request) {
                alert('Cannot create an XMLHTTP instance');
                return false;
            }

            request.onreadystatechange = handleJsonResponse.bind(this,request,callback);
            request.open(method, uri, true);
            request.send(null);
            return request;
        },

       jsonPost: function(uri, data, callback) {
            //uri += ((uri.indexOf('?') == -1) ? '?' : '&') + "version=" + new Date().valueOf().toString();
            var request = null;
            if (window.XMLHttpRequest) { 
                // Mozilla, Safari,...
                request = new XMLHttpRequest();
            } else if (window.ActiveXObject) { 
                // IE
                try {
                    request = new ActiveXObject("Msxml2.XMLHTTP");
                } catch (e) {
                    try {
                        request = new ActiveXObject("Microsoft.XMLHTTP");
                    } catch (e) {}
                }
            }
            
            if (!request) {
                alert('Cannot create an XMLHTTP instance');
                return false;
            }

            request.onreadystatechange = handleJsonResponse.bind(this,request,callback);
            request.open("POST", uri, true);

            if (typeof data === 'string') {
                request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            } else {
                request.setRequestHeader('Content-Type', 'application/json');
                if (data.toJSON)
                    data = data.toJSON();
                else
                    data = JSON.stringify(data);
            }
                
            request.send(data);
            return request;
        },
        
        getCookie: function() {
            var cookies = document.cookie.split(';');
            var peekeezCookie;
            for (c in cookies) if (cookies.hasOwnProperty(c)) {
                var cookie = cookies[c];
                if (cookie.indexOf("peekeez=") == 0) {
                    return cookie.substring(8);
                }
            }
        },
        
        navigateTo: function(url) {
            window.location = url;
        },

        launchWindow: function(name,url) {
            //window.open(url,name,"menubar=no,location=no,status=no,toolbar=no,height=400,width=580",true);
            var newWindow = window.open(url,name,"height=400,width=580",true);
            newWindow.blur();
            window.focus();
            return true;
        }
    };
})();

window.peekeez.verification = (function() {
    function requestVerificationEmail(event) {
        peekeez.util.jsonRequest("/ws/account/verify", function(results) {
            if (results) {
                console.log("Verification result: " + results);
                $('verification').update("A verification email has been sent to your email. Please check your email and follow the verification link.");
            }
        });
        event.stop();
        return false;
    }
    
    return {
        attachEventHandlers: function() {
            if ($('verify-link')) {
                $('verify-link').observe('click',requestVerificationEmail);
            }
        }
    }
})();

window.peekeez.cameraManager = (function() {
    var ownedCameras = null;
    var sharedCameras = null;
    var selectedCamera = null;
    var cameraListDiv;
    var currentTab = null;
    var serializedCameraList = null;
    var promoShown = false;
    
    var B = {};
    Builder.dump(B); 

    function initialize() {
        cameraListDiv = $('cameralist');
        if (cameraListDiv)
            startStatusPolling();
    }
    
    function startStatusPolling() {
        loadCameraList();
        new PeriodicalExecuter(function(pe) { 
            loadCameraList();
        }, 10);
    }
    
    function loadCameraList() {
        peekeez.util.jsonRequest("/ws/cameras", onCamerasReceived);
    }
    
    function revealPromoDiv() {
        if (!promoShown) {
            $('promo').show();
            new Effect.Move('promo', {x:0,y:-25,mode:'relative'});
            promoShown = true;
        }
    }

    function hidePromoDiv() {
        if (promoShown) {
            new Effect.Move('promo', {x:0,y:25,mode:'relative'});
            promoShown = false;
        }
    }

    // create the HTML for a single camera
    function createCameraDiv(camera,owned) {
        var imgUri = '/cameras/' + camera.client_ident + '/' + camera.camera_ident + '/icon.jpg';
        
        var isSelected = (selectedCamera != null && camera.client_ident == selectedCamera.client_ident && camera.camera_ident == selectedCamera.camera_ident);
        if (isSelected)
            selectedCamera = camera;
        var cameraDiv = B.DIV({className:(isSelected ? 'tab active' : 'tab')});
        cameraDiv.observe('click',cameraTabClicked.curry(camera));
   
        // generate the status string
        var status;
        var offline;
        if (camera.online) {
            offline = false;
            // --- viewer count is not reliable right now
            // var pluralSuffix;
            // if (camera.viewers == 1)
            //     pluralSuffix = "";
            // else
            //     pluralSuffix = "s";
            // status = "Online. " + camera.viewers + " viewer" + pluralSuffix;
            status = "Online";
        } else {
            if (camera.is_polling) {
                status = "Connected";
                offline = false;
            } else {
                offline = true;
                status = "Offline";
            }
        }
        
        var nameDiv = B.DIV({className:'name'},camera.name);
        cameraDiv.appendChild(nameDiv);
        
        var iconDiv = B.DIV({className:'icon'},B.IMG({border:'0',src:imgUri,width:'106',height:'80'}));
        cameraDiv.appendChild(iconDiv);
        if (offline) {
            var offlineDiv = B.DIV({className:'offline'});
            cameraDiv.appendChild(offlineDiv);
        }
        var playDiv = B.DIV({className:'play'});
        cameraDiv.appendChild(playDiv);
        var deleteDiv = B.DIV({className:'delete'});
        deleteDiv.observe('click',cameraDeleteClicked.curry(camera));
        cameraDiv.appendChild(deleteDiv);
        cameraDiv.appendChild(B.DIV({className:'status'},status));
        
        /*
        //---------------------------
        // this is for debugging only
        cameraDiv.appendChild(B.DIV({className:'ident'},camera.client_ident + ':' + camera.camera_ident));
        cameraDiv.appendChild(B.DIV({className:'ident'},camera.local ? "LOCAL" : "REMOTE"));
        //---------------------------
        */
        
        return cameraDiv;
    }
    
    function cameraState(camera) {
        if (!camera)
            return "null";
        if (camera.online) {
            return "Online";
        } else {
            if (camera.is_polling) {
                return "Connected";
            } else {
                return "Offline";
            }
        }
    }
    
    // callback for JSON request to get users cameras
    function onCamerasReceived(results) {
        if ((results) && ("status" in results)) {
            if (results.status == 0) {
                handleCameraResults(results);
            } else {
                peekeez.util.navigateTo("/action/logout");
            }
        } 
    }
    
    function handleCameraResults(results) {
        $('loading').hide();
        var resultsJson = JSON.stringify(results);
        //console.log("Camera list: " + resultsJson);
        // check if the camera list has changed
        if (resultsJson != serializedCameraList) {
            serializedCameraList = resultsJson;

            // if it has changed, we need to re-draw the camera list area
            ownedCameras = results.cameras.owned || [];
            sharedCameras = results.cameras.shared || [];
            
            if (ownedCameras.length == 0 && sharedCameras.length == 0) {
                //console.log("Camera lists are empty");
                $('empty-selector').show();
                $('empty-body').show();
                $('selector-tabs').hide();
                $('tabs').hide();
                $('viewer').hide();
                $('offline').hide();
                return;
            } else {
                $('empty-selector').hide();
                $('empty-body').hide();
                $('selector-tabs').show();
            }
            
            var cameraToSelect = null;
            if (selectedCamera == null) {
                var cameraToSelect = ownedCameras.length > 0 ? ownedCameras[0] : (sharedCameras.length > 0 ? sharedCameras[0] : null);
                if (cameraToSelect != null) {
                    //console.log("Selecting camera: " + cameraToSelect.client_ident + ":" + cameraToSelect.camera_ident);
                    selectedCamera = cameraToSelect;
                }
            }
            
            // get the current state of the selected camera
            var initialSelectedCameraState = cameraState(selectedCamera);
             
            var canUpgrade = false;   
            cameraListDiv.update("");
            ownedCameras.each(function(c) {
                c.owned = true;
                if (c.recording != 1) {
                    //console.log("camera " + c.camera_ident + " is not a recording camera.");
                    canUpgrade = true;
                }
                var cameraDiv = createCameraDiv(c,true);
                c.tab = cameraDiv;
                cameraListDiv.appendChild(cameraDiv);
            });

            sharedCameras.each(function(c) {
                c.owned = false;
                var cameraDiv = createCameraDiv(c,false);
                c.tab = cameraDiv;
                cameraListDiv.appendChild(cameraDiv);
            });
            
            if (canUpgrade)
                revealPromoDiv();
            else
                hidePromoDiv();
            
            // if we are changing the selection of the camera do that now
            if (cameraToSelect) {
                selectCamera(cameraToSelect.tab,cameraToSelect);
            } else {
                // see if the camera state of the selected camera is changing. if so, we need to refresh the content area
                var currentSelectedCameraState = cameraState(selectedCamera);
                //console.log("Prior selected camera state: " + initialSelectedCameraState + ", current state: " + currentSelectedCameraState );
                
                // we update the content area if:
                // 1) there is a selected camera,
                // 2) the selected camera has had a state change, 
                // 3) the state change is not from "connected" -> "online"
                // 4) the live view is being shown
                if (selectedCamera != null && 
                    currentSelectedCameraState != initialSelectedCameraState && 
                    !(currentSelectedCameraState == "Online" && initialSelectedCameraState == "Connected" ) &&
                    currentTab == "live") {
                   showContentForCamera(selectedCamera); 
                }
            }

        } else {
            //console.log("camera list has not changed");
        }
    }
    
    function deleteCamera(client_ident,camera_ident) {
        if (confirm("Are you sure you want to delete this camera?")) {
            peekeez.util.jsonRequest("/ws/camera/" + client_ident + "/" + camera_ident, function(result) {
                if (result && "status" in result && result.status == 0) {
                    var cameraToSelect = ownedCameras.length > 0 ? ownedCameras[0] : (sharedCameras.length > 0 ? sharedCameras[0] : null);
                    if (cameraToSelect != null) {
                        selectCamera(cameraToSelect.tab,cameraToSelect);
                    }
                } else {
                    // should we alert the user here??
                }
                // force a reload of the cameras
                loadCameraList();
            }, {method:"DELETE"});
        }
    }

    function showDefaultView() {
        peekeez.util.htmlUpdateRequest("/app/default", $('main'));
    }
    
    function showCameraEditor(camera) {
        peekeez.util.htmlUpdateRequest("/app/edit/" + camera.client_ident + "/" + camera.camera_ident + "/", $('settings'), peekeez.editcamera.initialize);
    }

    function setTabActive(e) {
        $$('.content .body .tabs li').each(function(elt) {
            elt.removeClassName('active');
        });
        if (e)
            $(e).up().addClassName('active');
    }

    function createFlashControl(camera,showLive) {
        /*
           <div class="tabs">
                <div class="tab active"><a href="/app/view/<?= $client_ident ?>/<?= $camera_ident ?>/">live</a></div>
                <div class="tab inactive"><a href="/app/history/<?= $client_ident ?>/<?= $camera_ident ?>/">history</a></div>
            </div>
            <div class="viewer" id="viewer">
            </div>
        */

        var controlText;
        if (showLive) {
            var params = $H({client:camera.client_ident, camera:camera.camera_ident, server:camera.media_server});
            controlText = peekeez.util.makeFlashObject("VideoViewer","17",640,480,'#000000',params.toQueryString());
        } else {
            var params = $H({client:camera.client_ident, camera:camera.camera_ident, days:camera.recording_retention});
            controlText = peekeez.util.makeFlashObject("RecordingViewer","8",640,541,'#000000',params.toQueryString());
		}
		
        var controlDiv = $('control');
        
        // create the control within the div
	    controlDiv.innerHTML = controlText;
    }
    
    function showLiveViewer(camera) {
        if (!camera.online && !camera.is_polling) {
            showOfflineContentForCamera(camera);
            return;
        }
        createFlashControl(camera,true);
        $('control').show()
        $('settings').hide();
        $('upgrade').hide();
        $('control').removeClassName('history');
        $('control').addClassName('live');
    }

    function showHistoryViewer(camera) {
        // check if this is a recording camera. if not, we offer an upgrade promotion instead of showing
        // the history control.
        //console.log("showing history tab for camera " + camera.client_ident + "/" + camera.camera_ident + ". recording = " + camera.recording + ", retention = " + camera.recording_retention );
        
        $('offline').hide();
        $('viewer').show();
        $('settings').hide();

        if (camera.recording == 1) {
            createFlashControl(camera,false);
            $('control').removeClassName('live');
            $('control').addClassName('history');
            $('control').show()
            $('upgrade').hide();
        } else {
            $('control').hide()
            $('upgrade').show();
        }
    }
    
    function showTabsForCamera(camera) {
        $('tabs').show();
        if (camera.owned)
            $('settings-tab-holder').show();
        else
            $('settings-tab-holder').hide();
        if (camera.owned == true || camera.recording == 1)
            $('history-tab-holder').show();
        else
            $('history-tab-holder').hide();
    }
    
    function showOfflineContentForCamera(camera) {
        //console.log("Showing offline content");
        $('viewer').hide();
        showTabsForCamera(camera);
        setTabActive(null);
        $('offline').show();
    }
    
    function showContentForCamera(camera) {
        var state = cameraState(camera);
        if (state == "Connected" || state == "Online") {
            showLiveViewer(camera);
            $('offline').hide();
            $('viewer').show();
            showTabsForCamera(camera);
            setTabActive($('live-tab'));
        }
        
        if (state == "Offline") {
            showOfflineContentForCamera(camera);
        }
        
        currentTab = "live";
    }
    
    function selectCamera(cameraTab,camera) {
        selectedCamera = camera;
        $$('.cameras .tab').each(function(elt) {
            elt.removeClassName('active');
        });
        cameraTab.addClassName('active');
        showContentForCamera(camera);
    }

    function cameraTabClicked(camera) {
        //console.log("Camera tab " + this + ": " + this.className + " for camera " + camera.client_ident + "/" + camera.camera_ident + " clicked");
        selectCamera(this,camera);
        return false;
    }

    function cameraDeleteClicked(camera) {
        //console.log("Camera delete button " + this + ": " + this.className + " for camera " + camera.client_ident + "/" + camera.camera_ident + " clicked");
        deleteCamera(camera.client_ident,camera.camera_ident);
        return false;
    }

    
    // have our initialize method called when the dom has fully loaded
    document.observe('dom:loaded', initialize );
    
    return {
        loadCameraList: loadCameraList,
        showDefaultView: showDefaultView,
        deleteCamera: deleteCamera,
        
        onLiveTabClicked: function(e) {
            if (selectedCamera) {
                //console.log("live tab clicked. selected camera = " + selectedCamera.client_ident + "/" + selectedCamera.camera_ident); 
                setTabActive(e);
                showLiveViewer(selectedCamera);
                currentTab = "live";
            }
            return false;
        },
        
        onHistoryTabClicked: function(e) {
            if (selectedCamera) {
                //console.log("history tab clicked. selected camera = " + selectedCamera.client_ident + "/" + selectedCamera.camera_ident);
                setTabActive(e);
                showHistoryViewer(selectedCamera);
                currentTab = "history";
            }
            return false;
        },
        
        onSettingsTabClicked: function(e) {
            if (selectedCamera && selectedCamera.owned) {
                //console.log("settings tab clicked. selected camera = " + selectedCamera.client_ident + "/" + selectedCamera.camera_ident);
                setTabActive(e);
                $('control').hide();
                $('upgrade').hide();
                $('settings').show();
                
                $('offline').hide();
                $('viewer').show();
                $('tabs').show();
                
                $('settings').update(B.DIV({className:'loading'},"Loading..."));
                showCameraEditor(selectedCamera);
                
                currentTab = "settings";
            }
            return false;
        }
        
    };
})();

function object(p) {
    function F() {}
    F.prototype = p;
    var o = new F();
    if (typeof o.initialize === 'function') {
        Array.prototype.shift.call(arguments);
        o.initialize.apply(o, arguments);
    }
    return o;
}
