/*
 * Copyright (c) 2006-2007 Collactive. All rights reserved.
 */
var SiteAutomationFacade = function(name) {
	this.name = name;
	this._config = {};

    this._assistInfo = {
        clientRequired: false,
        acccountRequired: false
    };

	this.init = function(ui, url, elem, actions) {
		this._isActive = true;
		this._ui = ui;
		this._uiDisplayed = false;
		this._ui.addDisplayListener({onShow: Collactive.bind(this, function() { this._displayListener(true)} ),
									onHide: Collactive.bind(this, function() { this._displayListener(false)} ),
									onSmallMode: Collactive.bind(this, function() { this._displayListener(false, true);} )
									});

		this._config = typeof(getPointConfig) != "undefined" ? getPointConfig() : {};

		this._hasCSA = Collactive.CSAUtils.hasCSA();
		if (this._hasCSA) {
			this._csaEngineVersionSatisfactory = Collactive.CSAUtils.isCSAEngineVersionSatisfactory(this._config);
			this._storage = new Collactive.CSAStorage();
			Collactive.CSAUtils.waitForAPIReady(Collactive.bind(this, function() {
				this._initReady(url, elem, actions);
			}));
		} else {
			this._storage = new Collactive.CookieStorage();
			this._initReady(url, elem, actions);
		}
	};

	this._initReady = function(url, elem, actions) {
		this._assistant = this._createAssistant();
		var notifyCallback = Collactive.bind(this, function() {
			var name = arguments[0];
			var args = [];
			for (var i = 1; i < arguments.length; ++i) {
				args.push(arguments[i]);
			}
			if (this[name] == null) {
				throw ("no such state in facade: [" + name + "]");
			}
			this[name].apply(this, args);
    	});

		// Do this anyway, we might use the proxy
	    Collactive.SSAUtils.init(notifyCallback, elem);
		if (this._hasCSA) {
			Collactive.CSAUtils.init(notifyCallback);
			Collactive.CSAUtils.disableStaticMapping();
			this._mapCSA();
		}

		// If we have the IFRAME element, set its source to the URL chosen.
		if (elem) {
			this.elem = elem;
			this.elem.src = url;
		}

		return url;
	};
	
	this.consoleLog = function(o){
		if (this._config && this._config.developmentMode && window.console && window.console.log) {
			window.console.log(o);
		}
	}
	this.debugBreak = function(){
		debugger;
	}

	this._navigateTo = function(url) {
		if (this._saAPI) {
			var location = this._saAPI.getLocation();
		} else {
			var location = this.elem.src;
		} 
    	if (location != url && location != Collactive.ProxyUtils.proxify(url)) {
	        this.elem.src = url;
    	}
	};

    this._setActionSettings = function(actionSettings) {
        this._actionSettings = actionSettings;
    };

	this._setSAMapping = function(includeList, excludeList, scriptsList) {
		this._saIncludeList = includeList;
		this._saExcludeList = excludeList;
		this._saScriptsList = scriptsList;
	};

	this._mapCSA = function() {
		Collactive.CSAUtils.map(this._assistant.shortName(), this._saIncludeList, this._saExcludeList, this._saScriptsList);
	};

	this.getWebservicesURLPrefix = function() {
		return this._config.webservicesURLPrefix;
	};

	this.proxify = function(url) {
		return Collactive.ProxyUtils.proxify(url);
	};

	this.getIsAnimationEnabled = function() {
		return this._config.animationEnabled;
	};

	this.getAnimationSpeed = function() {
		return this._config.animationSpeed;
	};

    this._assistedFunction = function(options, func) {
        if (options.clientOnly) {
            this._assistInfo.clientRequired = true;
        }
        if (options.accountRequired) {
            this._assistInfo.accountRequired = true;
        }

        // TODO: here add options to something and remememer if we are client/server
        return function() {
            args = arguments;

			if (options.navigateFirst) {
		        this._navigateTo(args[0]);
			}

			if (options.serverOnly) { // Server only mode
			    if (!this._hasSSA()) {
	    		    // Get rid of API, we might have got it from the client
	    		    this._saAPI = null;
	    		    Collactive.SSAUtils.activateProxy();
			   	}

			} else if (options.clientOnly) { // Client only mode
			    if (!this._hasCSA || !this._csaEngineVersionSatisfactory) {
					throw "CSARequired";
			    }

			} else { // Use client if available, otherwise server
			    if (!this._hasCSA && !this._hasSSA()) {
	    		    Collactive.SSAUtils.activateProxy();
			    }
			}

			this.waitForSAReady(Collactive.bind(this, function() {
			    try {
    	            return func.apply(this, args);
			    } catch (e) {
			        if (this._saAPI != null) {
			            this._saAPI.notifyError("Exception caught by facade: " + (e.description || e), e);
			        } else {
			            this._assistant.notifyError({
			                error: "Exception caught with no SA: " + (e.description || e),
			                func: func.toString(),
			                name: this.name,
                            state: this._storage.loadSession("sa_state"),
                	        url: document.location.toString(),
                	        referrer: document.referrer,
                	        userAgent: navigator.userAgent,
                	        platform: navigator.platform
			            }, "Exception caught with no SA: " + (e.description || e));
			        }
			    }
			}));
        };
    };

    this.notifyError = function(params, msg) {
        this._assistant.notifyError(params, msg);
    };

	this._asyncCallback = function(func) {
		this._asyncCallbackFunc = Collactive.bind(this, func);
		return '_asyncCallbackFunc';
	};

	this._asyncCallback2 = function(func) {
		var r = Math.floor(Math.random()*1000000);
		this['_asyncCallbackFunc' + r] = Collactive.bind(this, func);
		return '_asyncCallbackFunc' + r;
	};

    this.isClientRequired = function() {
        return this._assistInfo.clientRequired;
    };

    this.isAccountRequired = function() {
        return this._assistInfo.accountRequired;
    };

    this.isClientInstallationRequired = function() {
        return this.isClientRequired() && (!this._hasCSA || !this._csaEngineVersionSatisfactory);
    };

    this.getSATimeout = function() {
        return 60 * 1000;
    };

	this._hasSSA = function() {
	    try {
    	    return (this.elem.contentWindow.Collactive_start != null);
    	} catch (e) {
    	    // Possibly catch permission problems
    	}
    	return false;
	};

	this.onSAReady = function(api) {
		this._saAPI = api;
		this._saAPI.init(this);

        if (this._uiDisplayed) {
    	    this._saAPI.invisiblize();
    	}

	    this._ui.setHideMode(false);

		this._saAPI.next();
	};

	this.onSAUnload = function() {
		this._saAPI = null;
	    this._ui.resetHideMode();
	};

	this.waitForSAReady = function(callback) {
        if (this._saAPI != null) {
            callback();
            return;
        }

        this._waitForSAReadyStart = new Date().getTime();
        this._assistant.reportLoadingStatus();
        setTimeout(Collactive.bind(this, function() { this.waitForSAReadyTimer(callback); }), 100);
	};

	this.waitForSAReadyTimer = function(callback) {
        if (this._saAPI != null) {
            this._waitForSAReadyStart = null;
            callback();
        } else {
            if (new Date().getTime() > (this._waitForSAReadyStart + this.getSATimeout())) {
                this._assistant.notifyError({
                    error: "waitForSAReady expired",
                    state: this._storage.loadSession("sa_state"),
                    name: this.name,
        	        url: document.location.toString(),
        	        referrer: document.referrer,
        	        userAgent: navigator.userAgent,
        	        platform: navigator.platform
                }, "waitForSAReady expired");

                return;
            }
            setTimeout(Collactive.bind(this, function() { this.waitForSAReadyTimer(callback); }), 100);
        }
	};

	this._displayListener = function(displayed, smallmode) {

        this._uiDisplayed = displayed;
        if (this._saAPI == null) {
            return;
        }

        if (this._uiDisplayed) {
            this._saAPI.invisiblize();
        } else {
            this._saAPI.visiblize();
        }
        if (smallmode) {
            this._saAPI.enterSmallMode();
        }
	};
	
	this.bind = function(f) {
	     var thisObject = this;
	     return function() {
		     var args2 = [];
		     for (var i = 0; i < arguments.length; i++) {
		         args2.push(arguments[i]);
		     }
		     return f.apply(thisObject, args2);
	     };
	};	

	this.deactivate = function() {
		this._isActive = false;
		if (Collactive.CSAUtils.hasCSA()) {
			Collactive.CSAUtils.clearMapping();
		}
	};

	this.autoLogInFailed = function() {
	    this._saAPI.autoLogInFailed();
	};

	this._setSAMapping(CollactiveSiteInfo[name].includeList,
					   CollactiveSiteInfo[name].excludeList,
					   CollactiveSiteInfo[name].scriptURLs);

    this.login = function(url, callback, username, password, email) {
	    this.loginAndPerform(url, callback, Collactive.bind(this, function() {
                						callback(true);
                					}), username, password, email);

    };

    this.register = this._assistedFunction({
        navigateFirst: false,
        clientOnly: true,
        accountRequired: false
    }, function(callback) {
        this._saAPI.register(this._asyncCallback(function (status) { callback(status); }));
    });

    this.loginAndPerform = this._assistedFunction({
       	navigateFirst: true,
        clientOnly: true,
        accountRequired: true
    }, function(url, callback, actionFunc, username, password, email) {
		this._storage.clearSession();
		this._saAPI.login(this._asyncCallback(function (status) {
			if (status) {
				this._saAPI.navigateTo(url, this._asyncCallback(function (status) {
					actionFunc();
				}));
			} else {
				callback(status);
			}
		}), username, password, email);
    });

    this.navigateAndPerform = this._assistedFunction({
       	navigateFirst: true,
        clientOnly: true,
        accountRequired: true
    }, function(url, actionFunc) {
		this._storage.clearSession();
		this._saAPI.navigateTo(url, this._asyncCallback(function (status) {
			actionFunc();
		}));
    });

    this.submit = function(url, story_url, type, title, description, category, tags, callback, username, password, email) {
	   	this.loginAndPerform(url, callback, Collactive.bind(this, function() {
        	this._saAPI.submitContent(story_url, type, title, description, category, tags, this._asyncCallback(function (status, url, error_code,message) {
				callback(status, url, error_code,message);
			}), true);
		}), username, password, email);
    };

    this.discuss = function(url, commentText, callback, username, password, email) {
	   	this.loginAndPerform(url, callback, Collactive.bind(this, function() {
        	this._saAPI.discuss(commentText, this._asyncCallback(function (status) {
            	callback(status);
			}), true);
		}), username, password, email);
    };
	this.replyToComment = function(url, commentId, replyText, callback, username, password, email) {
	   	this.loginAndPerform(url, callback, Collactive.bind(this, function() {
        	this._saAPI.replyToComment(commentId, replyText, this._asyncCallback(function (status, message) {
            	callback(status, message);
			}), true);
		}), username, password, email);
    };
    this.sendMessage = function(url, subject, content, callback, username, password, email) {
	   	this.loginAndPerform(url, callback, Collactive.bind(this, function() {
        	this._saAPI.sendMessage(subject, content, this._asyncCallback(function (status) {
            	callback(status);
			}), true);
		}), username, password, email);
    };	
	
    this.replyToMessage = function(url, messageID, subject, content, callback, username, password, email) {
	   	this.loginAndPerform(url, callback, Collactive.bind(this, function() {
        	this._saAPI.replyToMessage(messageID, subject, content, this._asyncCallback(function (status) {
            	callback(status);
			}), true);
		}), username, password, email);
    };

    this.inviteFriend = function(url, callback, username, password, email) {
	   	this.loginAndPerform(url, callback, Collactive.bind(this, function() {
        	this._saAPI.inviteFriend(this._asyncCallback(function (status) {
            	callback(status);
			}), true);
		}), username, password, email);
    };

    this.removeFriend = function(url, callback, username, password, email) {
	   	this.loginAndPerform(url, callback, Collactive.bind(this, function() {
        	this._saAPI.removeFriend(this._asyncCallback(function (status) {
            	callback(status);
			}), true);
		}), username, password, email);
    };

    this.share = function(url, friend_ids, message, callback, username, password, email) {
		this.loginAndPerform(url, callback, Collactive.bind(this, function() {
        	this._saAPI.share(friend_ids, message, this._asyncCallback(function (status) {
				callback(status);
			}), true);
		}), username, password, email, true);
		
    };

	this.vote = function(url, positive, callback, username, password, email) {
	    this.loginAndPerform(url, callback, Collactive.bind(this, function() {
            if (positive) {
                this._saAPI.vote(this._asyncCallback(function (status) {
                 						callback(status);
                 					}));
            } else {
                 this._saAPI.bury(this._asyncCallback(function (status) {
                 						callback(status);
                 					}));

            }
	    }), username, password, email);
	};
	
	this._debugDone = function() {
		this.consoleLog(arguments);
		getWizardUI().hide();
	}
	
	return this;
};
