(function() {
    'use strict';

    angular
        .module('app-base')
        .service('AppService', AppService)
        .service('AppSettings', AppSettings)
        .factory('AppData', AppData);

    /** @ngInject */
    function AppService($q,$rootScope,$log,$sce,$window,AppSettings) {

        this.initialize = function(options){
            var _this = this;
            var deferred = $q.defer();

            if(!options.scope){
                options.scope = $rootScope;
            }
            _this.scope = options.scope;
            _this.$broadcast = options.scope.$broadcast;
            _this.$on = options.scope.$on;

            options.scope.hasTouch = this.checkForTouchDevice();
            if ($window.verge) {
                $.extend($window.verge);
            }
            if(options.config_file){
                AppSettings.get(options.config_file).then(initApp);
            }else{
                initApp();
            }

            function initApp(){
                if(AppSettings.xdomain){
                    _this.setupXdomain(AppSettings.xdomain);
                }
                options.scope.settings = AppSettings;
                options.scope.protocol = $window.location.protocol;
                options.scope.trustAsSrc = function(src) {
                    return $sce.trustAsResourceUrl(src);
                };
                if(options.scope.hasTouch && $window.FastClick){
                    $window.FastClick.attach(document.body); // new FastClick(document.body);
                }
                if ("withCredentials" in new XMLHttpRequest) {
                    options.scope.cors = true;
                }
                $window.console = $window.console || (function() {
                    var c;c = {};c.log = c.warn = c.debug = c.info = c.error = c.time = c.dir = c.profile = c.clear = c.exception = c.trace = c.assert = function() {};
                    return c;
                })();
                _this.ready = AppSettings.ready = true;
                //$log.debug('AppService: app-ready');
                options.scope.$broadcast('app-ready');
                deferred.resolve();
            }
            return deferred.promise;
        };

        this.setupXdomain = function(object){
            if($window.xdomain){
                $window.xdomain.masters(object.masters);
                $window.xdomain.slaves(object.slaves);
            }
        };

        this.saveLocalModel = function(model,modelName){
            var id = modelName || 'model';
            if($window.localStorage){
                $window.localStorage.setItem(id+'-json',JSON.stringify(model));
                $window.localStorage.setItem(id+'-json-changed',this.getTimeStamp());
                $log.log("saveLocalModel() :: "+id+" :: "+ $window.localStorage.getItem(id+'-json-changed') )
            }
        };

        this.restoreLocalModel = function(modelName){
            var model = modelName || 'model';
            if($window.localStorage){
                return JSON.parse(localStorage.getItem(model+'-json'));
            }
        };

        this.checkForTouchDevice = function() {
            var _ref;
            return (_ref = typeof $window.ontouchstart !== 'undefined') != null ? _ref : {
                "true": false
            };
        };

        this.isOnline = function() {
            if ($window.navigator.onLine) {
                return true;
            } else {
                return false;
            }
        };

        this.getTimeStamp = function() {
            return Math.round(+new Date()/1000);
        };

        this.getUUID = function() {
            var d = new Date().getTime();
            var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
                var r = (d + Math.random()*16)%16 | 0;
                d = Math.floor(d/16);
                return (c=='x' ? r : (r&0x7|0x8)).toString(16);
            });
            return uuid;
        };
    }

    /** @ngInject */
    function AppSettings($q,$log,$window,AppData) {
        this.baseUrl = "";
        this.path_to_templates = "";
        this.path_to_lib = "http://dl.dropboxusercontent.com/u/1037880/libraries/app-base";

        this.get = function(url){
            var self = this
            var deferred = $q.defer();
            if(url.match('jsonp') || url.match('getParams')){
                AppData.getJSONP(url).then(function(data){
                    self.add(data);
                    deferred.resolve(data);
                });
            }else{
                AppData.get(url).then(function(data){
                    self.add(data);
                    deferred.resolve(data);
                });
            }
            return deferred.promise;
        };
        this.add = function(object){
            for(var k in object){
                this[k] = this.castToType(object[k])
            }
        };
        this.saveLocal = function() {
            if($window.localStorage){
                var obj = {};
                angular.forEach(this,function(value,key){
                    // todo: check for arrays / objects bug
                    if(typeof(value)!="function"){obj[key]=value}
                });
                //for(var k in this){
                //    if(typeof(this[k])!="function"){obj[k]=this[k]}
                //}
                $window.localStorage.setItem('appsettings-json',JSON.stringify(obj));
                $window.localStorage.setItem('appsettings-json-changed',Math.round(+new Date()/1000));
            }
        };
        this.restoreLocal = function() {
            if($window.localStorage){
                var obj = JSON.parse($window.localStorage.getItem('appsettings-json'));
                for(var k in obj){
                    this[k]=this.castToType(obj[k])
                }
            }
        };
        this.castToType = function(o) {
            var value = o;
            if (Number(value) && value !== "true" && value !== "false") {value = Number(value);}
            if (value === "0") {value = 0;}
            if (value === "true") {value = true;}
            if (value === "false") {value = false;}
            return value;
        };
    }

    /** @ngInject */
    function AppData($http,$q,$log) {
        return {
            get: function (url) {
                var deferred = $q.defer();
                $http.get(url).success(function (data, status, headers) {
                    deferred.resolve(data);
                }).error(function (data, status, headers) {
                    deferred.reject(status);
                });
                return deferred.promise;
            },
            getJSONP: function(url, callback, wrapping) {
                var deferred = $q.defer();
                if (wrapping == null) {wrapping = "JsonWrapping";}
                // fixme: needs jquery or zepto for static jsonp files
                return $.ajax({
                    url: url,
                    dataType: "jsonp",
                    cache: true,
                    jsonpCallback: wrapping,
                    success: function(result) {
                        deferred.resolve(result);
                    },
                    error: function() {
                        $log.error("jsonp load failed: " + url);
                        deferred.reject(status);
                    }
                });
                return deferred.promise;
            }

        }
    }

})();
