function getPageSize() {
    var xScroll, yScroll;
	
    if (window.innerHeight && window.scrollMaxY) {	
	xScroll = document.body.scrollWidth;
	yScroll = window.innerHeight + window.scrollMaxY;
    } else
    if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
	xScroll = document.body.scrollWidth;
	yScroll = document.body.scrollHeight;
    } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
	xScroll = document.body.offsetWidth;
	yScroll = document.body.offsetHeight;
    }
    
    var windowWidth, windowHeight;
    if (self.innerHeight) {	// all except Explorer
	windowWidth = self.innerWidth;
	windowHeight = self.innerHeight;
    } else 
    if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
	windowWidth = document.documentElement.clientWidth;
	windowHeight = document.documentElement.clientHeight;
    } else 
    if (document.body) { // other Explorers
	windowWidth = document.body.clientWidth;
	windowHeight = document.body.clientHeight;
    }	
    
    // for small pages with total height less then height of the viewport
    if (yScroll < windowHeight){
	pageHeight = windowHeight;
    } else { 
	pageHeight = yScroll;
    }
    
    // for small pages with total width less then width of the viewport
    if (xScroll < windowWidth) {	
	pageWidth = windowWidth;
    } else {
	pageWidth = xScroll;
    }
    
    return {page: {width: pageWidth, height: pageHeight}, window: {width: windowWidth, height: windowHeight}};
}

var Observable = Class.create();

Observable.prototype = {

    listeners: new Array(),

    initialize: function() {
    },

    addListener: function(listener) {
        this.listeners.push(listener);
    },

    removeListener: function(listener) {
        this.listeners = this.listeners.without(listener);
    },

    notify: function() {
        var listeners = this.listeners;
        for (var i = 0; i < listeners.length; ++i) {
            listeners[i].apply(this, arguments);
        }
    }

}

var Account = Class.create();

Account.prototype = Object.extend(new Observable(), {

    id: null,
    email: null,

    initialize: function(id, email) {
        if (id) {
            this.id = id;
        }
        if (email) {
            this.email = email;
        }
    },

    trial: function() {
        var dialog = new AccountTrialDialog(this);
        dialog.open();
    },

    join: function() {
        var dialog = new AccountJoinDialog(this);
        dialog.open();
    },

    login: function() {
        var dialog = new AccountLoginDialog(this);
        dialog.open();
    },

    logout: function() {
        var dialog = new AccountLogoutDialog(this);
        dialog.open();
    }

});

var ModalDialog = Class.create();

ModalDialog.prototype = {

    initialize: function() {
    },

    create: function(dialog) {},

    submit: function(dialog) {},

    createForm: function(dialog, fragment, submit) {
        new Insertion.Bottom(dialog,
            '<form class="form" onsubmit="return false">' +
            fragment +
            '<div class="error" style="display: none">Communication error - please try again later.</div>' +
            '<button type="submit" name="submit" class="submit">' + submit + '</button>' +
            '</form>'
        );
        var self = this;
        Event.observe(this.getElementByClassName('form'), 'submit', function() {self.submit()}, false);
    },

    open: function() {
        var size = getPageSize();

        var Safari = navigator.appVersion.match(/Konqueror|Safari|KHTML/);
        if (Safari && $('flashcontent')) {
            var fc = $('flashcontent');
            fc.style.position = 'relative';
            fc.style.top = size.page.height + 'px';
        }

        var self = this;
        this._resize = function() {self.resize()};
        Event.observe(window, 'resize', this._resize, false);
        var body = document.getElementsByTagName('body').item(0);
	
	var overlay = document.createElement('div');
	overlay.setAttribute('id', 'overlay');
	overlay.style.display = 'block';
	overlay.style.position = 'absolute';
	overlay.style.top = '0';
	overlay.style.left = '0';
 	overlay.style.width = size.page.width + 'px';
 	overlay.style.height = size.page.height + 'px';
	overlay.style.zIndex = '90';
        Event.observe(overlay, 'click', function() {self.close()}, false);
	body.insertBefore(overlay, body.firstChild);

        var dialog = document.createElement('div');
        dialog.setAttribute('id', 'dialog');
        dialog.style.display = 'block';
        dialog.style.position = 'absolute';
        dialog.style.top = '100px';
        dialog.style.left = ((size.page.width - 320) / 2) + 'px';
        dialog.style.width = '320px';
        dialog.style.zIndex = '100';
	body.insertBefore(dialog, overlay.nextSibling);
        this.create(dialog);
        var form = this.getElementByClassName('form');
        var first = Form.findFirstElement(form);
        if (first) {
            Field.activate(first);
        } else {
            Field.activate(this.getElementByClassName('submit'));
        }
    },

    resize: function() {
        var size = getPageSize();
        var overlay = document.getElementById('overlay');
 	overlay.style.width = size.page.width + 'px';
 	overlay.style.height = size.page.height + 'px';
    },

    closeForm: function() {
        Event.stopObserving(window, 'resize', this._resize, false);
        delete this._resize;

        var overlay = document.getElementById('overlay');
        overlay.parentNode.removeChild(overlay);

        var dialog = document.getElementById('dialog');
        dialog.parentNode.removeChild(dialog);

        var Safari = navigator.appVersion.match(/Konqueror|Safari|KHTML/);
        if (Safari && $('flashcontent')) {
            var fc = $('flashcontent');
            fc.style.position = 'block';
        }
    },

    close: function() {
        this.closeForm();
    },

    getElementByClassName: function(className) {
        return document.getElementsByClassName(className, $('dialog'))[0];
    },

    display: function(className, type) {
        this.getElementByClassName(className).style.display = type;
    },

    disable: function(className) {
        var element = this.getElementByClassName(className);
        element.blur();
        element.disabled = 'true';
    },

    enable: function(className) {
        var element = this.getElementByClassName(className);
        element.disabled = '';
    }

}

var MessageDialog = Class.create();

MessageDialog.prototype = Object.extend(new ModalDialog(), {

    initialize: function(fragment) {
        this.fragment = fragment;
    },

    create: function(dialog) {
        this.createForm(dialog, this.fragment, "close");
    },

    submit: function() {
        this.close();
    }

});

var RequestDialog = Class.create();

RequestDialog.prototype = Object.extend(new ModalDialog(), {

    initialize: function() {
    },

    success: function(dialog) {},

    createRequestForm: function(dialog, fragment, submit, assist) {
        var content =
            '<form class="form" onsubmit="return false">' +
            fragment +
            '<div class="error" style="display: none">Commmunication error - please try again later.</div>' +
            '<div class="refused" style="display: none">Error - please try again later.</div>' +
            '<div class="accepted" style="display: none">Success.</div>';
        if (assist) {
            content +=
                '<button type="button" name="assist" class="assist">' + assist + '</button>';
        }
        content +=
            '<button type="submit" name="submit" class="submit">' + submit + '</button>' +
            '<button type="button" name="cancel" class="cancel">cancel</button>' +
            '</form>';
        new Insertion.Bottom(dialog, content);
        var self = this;
        if (assist) {
            Event.observe(this.getElementByClassName('assist'), 'click', function() {self.assist()}, false);
        }
        Event.observe(this.getElementByClassName('cancel'), 'click', function() {self.close()}, false);
        Event.observe(this.getElementByClassName('submit'), 'click', function() {self.submit()}, false);
        Event.observe(this.getElementByClassName('form'), 'submit', function() {self.submit()}, false);
    },

    close: function() {
        if (this['request']) {
            this.request.transport.abort();
        }
        this.closeForm();
    },

    submitRequest: function(uri, parameters) {
        this.display("error", "none");
        this.display("refused", "none");
        this.display("accepted", "none");
        if (parameters) {
            var query;
            for (var name in parameters) {
                if (query) {
                    query = query + "&";
                } else {
                    query = "?";
                }
                query = query + escape(name) + "=" + escape(parameters[name]);
            }
            if (query) {
                uri = uri + query;
            }
        }
        var self = this;
        this.request = new Ajax.Request(uri, {
            onException: function(r, e) {/*alert('exception: ' + e.name + ': ' + e.message);*/ self.failure()},
            onFailure: function() {self.failure()},
            onSuccess: function() {self.success()}
        });
        this.enable("cancel");
        this.disable("submit");
    },

    failure: function() {
        this.display("error", "block");
        this.enable("submit");
        this.request = null;
    },

    notify: function(id, email) {
        this.observable.id = id;
        this.observable.email = email;
        this.observable.notify(id, email);
    },

    showRefused: function(message) {
        var refused = this.getElementByClassName("refused");
        refused.innerHTML = message;
        this.display("refused", "block");
    },

    success: function() {
        var xml = this.request.transport.responseXML;
        this.request = null;
        var faultstrings = xml.getElementsByTagName("faultstring");
        if (faultstrings.length > 0) {
            this.showRefused(faultstrings[0].firstChild.nodeValue);
            this.enable("submit");
            return;
        }

        var successstrings = xml.getElementsByTagName("successstring");
        if (successstrings.length > 0) {
            var accepted = this.getElementByClassName("accepted");
            accepted.innerHTML = successstrings[0].firstChild.nodeValue;
            this.display("accepted", "block");
            this.enable("submit");
            return;
        }

        var accounts = xml.getElementsByTagName("account");
        if (accounts.length > 0) {
            var account = accounts.item(0);
            var valid = account.getAttribute("valid") == "true";
            var id = account.getAttribute("id");
            if (id == undefined) {
                id = null;
            }
            var email = account.getAttribute("email");
            if (email == undefined) {
                email = null;
            }
        }
        if (this.redirect) {
            window.location = this.redirect;
        }
        this.close();
        this.notify(id, email);
    }

});

var AccountTrialDialog = Class.create();

AccountTrialDialog.prototype = Object.extend(new RequestDialog(), {

    initialize: function(observable) {
        this.observable = observable;
    },

    create: function(dialog) {
        this.createRequestForm(dialog,
            '<div class="text">' +
            'Trial accounts are temporary.  You can convert your trial account ' +
            'into a permanent account at any time by joining.  Others can view ' +
            'your public movies if you join.' +
            '</div>',
            'start trial'
        );
    },

    redirect: "/create.jsp",

    submit: function() {
        this.submitRequest("/TrialAccount");
    }

});

var AccountJoinDialog = Class.create();

AccountJoinDialog.prototype = Object.extend(new RequestDialog(), {

    initialize: function(observable) {
        this.observable = observable;
    },

    create: function(dialog) {
        this.createRequestForm(dialog,
            '<div class="text">' +
            'Please provide us with the following account information:' +
            '</div>' +
            '<table class="panel" cellpadding="0" cellspacing="0">' +
            '<tr class="entry"><td class="label">email:</td><td class="field"><input class="email" type="text"></td></tr>' +
            '<tr class="entry"><td class="label">password:</td><td class="field"><input class="password" type="password"></td></tr>' +
            '<tr class="entry"><td class="label">confirm:</td><td class="field"><input class="confirm" type="password"></td></tr>' +
            '</table>',
            'join'
        );
    },

    redirect: "/create.jsp",

    submit: function() {
        var email = $F(this.getElementByClassName("email"));
        var password = $F(this.getElementByClassName("password"));
        var confirm = $F(this.getElementByClassName("confirm"));
        if (password != confirm) {
            this.showRefused("Password doesn't match confirm - please enter them again.");
            return;
        }
        if (this.observable.id) {
            this.submitRequest("/RegisterAccount", {accountId: this.observable.id, email: email, password: password});
        } else {
            this.submitRequest("/RegisterAccount", {email: email, password: password});
        }
    },

    notify: function(id, email) {
        var dialog = new MessageDialog(
            '<p>Thank you for joining!</p>'
        );
        var self = this;
        dialog.submit = function() {
            self.observable.id = id;
            self.observable.email = email;
            self.observable.notify(id, email);
            dialog.close();
        };
        dialog.open();
    }

});

var AccountLoginDialog = Class.create();

AccountLoginDialog.prototype = Object.extend(new RequestDialog(), {

    initialize: function(observable) {
        this.observable = observable;
    },

    create: function(dialog) {
        this.createRequestForm(dialog,
            '<div class="text">' +
            'Please provide us with your account information:' +
            '</div>' +
            '<table class="panel" cellpadding="0" cellspacing="0">' +
            '<tr class="entry"><td class="label">Email Address:</td><td class="field"><input class="email" type="text"></td></tr>' +
            '<tr class="entry"><td class="label">Password:</td><td class="field"><input class="password" type="password"></td></tr>' +
            '</table>',
            'login',
            'email password'
        );
    },

    redirect: "/create.jsp",

    assist: function() {
        var email = $F(this.getElementByClassName("email"));
        this.submitRequest("/RecoverPassword", {email: email});
    },

    submit: function() {
        var email = $F(this.getElementByClassName("email"));
        var password = $F(this.getElementByClassName("password"));
        this.submitRequest("/QueryAccount", {email: email, password: password});
    }

});

var AccountLogoutDialog = Class.create();

AccountLogoutDialog.prototype = Object.extend(new RequestDialog(), {

    initialize: function(observable) {
        this.observable = observable;
    },

    redirect: "/",

    create: function(dialog) {
        this.createRequestForm(dialog,
            '<div class="text">' +
            'Logout?' +
            '</div>',
            'logout'
        );
    },

    submit: function() {
        this.submitRequest("/LogoutAccount");
    }

});

Object.extend(Event, {
  _domReady : function() {
    if (arguments.callee.done) return;
    arguments.callee.done = true;

    if (this._timer)  clearInterval(this._timer);

    this._readyCallbacks.each(function(f) { f() });
    this._readyCallbacks = null;
},
  onDOMReady : function(f) {
    if (!this._readyCallbacks) {
      var domReady = this._domReady.bind(this);

      if (document.addEventListener)
        document.addEventListener("DOMContentLoaded", domReady, false);

        /*@cc_on @*/
        /*@if (@_win32)
            document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
            document.getElementById("__ie_onload").onreadystatechange = function() {
                if (this.readyState == "complete") domReady(); 
            };
        /*@end @*/

        if (/WebKit/i.test(navigator.userAgent)) { 
          this._timer = setInterval(function() {
            if (/loaded|complete/.test(document.readyState)) domReady(); 
          }, 10);
        }

        Event.observe(window, 'load', domReady);
        Event._readyCallbacks =  [];
    }
    Event._readyCallbacks.push(f);
  }
});

function resizeContents() {
    var lzapp = document.getElementById('lzapp');
    if (!lzapp) {
        return;
    }

    var size = getPageSize();
    var contents = document.getElementById('contents');
    var footer = document.getElementById('footer');
    var height = size.window.height - 16 - contents.offsetTop - footer.offsetHeight - 16;

    // work around IE 6 bug - doesn't respect min-height -denis
    if (height < 400) {
        height = 400;
    }

    contents.style.height = height + "px";

    // work around IE 6 bug - where only horizontal resize updates flash size -denis
//    var lzapp = document.getElementById('lzapp');
//    if (lzapp) {
        lzapp.height = height + "px";
//    }

    // work around IE 6 bug - doesn't respect min-width -denis
    var width = size.window.width - 16;
    if (width < 600) {
        width = 600;
    }
    document.body.style.width = width + "px";
}

var account = new Account();

function disableLink(element) {
    var a = $(element).firstChild;
    a.addClassName('disabled');
    a.removeAttribute('href');
}

function enableLink(element, href) {
    var a = $(element).firstChild;
    a.removeClassName('disabled');
    a.setAttribute('href', href);
}

function updateAccountItems() {
    if (!account.id) {
        Element.show('join');
        Element.show('login');
        Element.hide('logout');
        Element.hide('account');
        Element.hide('create');
        document.title = 'tracking shot'
        $('title').innerHTML = '<a href="/">tracking shot</a>';
    } else {
        Element.hide('join');
        Element.hide('login');
        Element.show('logout');
        Element.show('account');
        Element.show('create');
        if (!account.email) {
            document.title = 'tracking shot - trial'
            $('title').innerHTML = '<a href="/">tracking shot</a> - trial';
        } else {
            document.title = 'tracking shot - ' + account.email;
            $('title').innerHTML = '<a href="/">tracking shot</a> - ' + escape(account.email);
        }
    }
}

account.addListener(function() {
    updateAccountItems();

    var lzapp = document.getElementById('lzapp');
    if (lzapp) {
        lzapp.accountChanged();
    }
});
