// fixme: cannot set to base-app
angular.module('app-base.drupal-service', ['ngResource'])
//angular.module('base-app', ['ngResource'])

    .service('DrupalService',['$http','$cookies','$q','$resource','$rootScope','$window','AppSettings','AppService','AppData',function($http,$cookies,$q,$resource,$rootScope,$window,AppSettings,AppService,AppData){
        var _this = this;
        this.model = this.data = {
            nodes:{},
            views:{},
            menus:{},
            siteParams:{}
        };
        this.sites = {};
        this.default_pass = '9+4v2Fvm32/8bke';
        this.default_user = 'services';
        //this.token_hash = 'ff4a52397b73edb1568dd93913fea8e56f81f988a89be62a3ed953767e11c920697e1ae4c2913133d8c25139c60517d683e6ba4dd21e324f3d2cf0cd1d15abf1';
        $window.Drupal = $window.Drupal || {};
        $window.Drupal.settings = $window.Drupal.settings || {};

        this.init = function(options){
            var defer = $q.defer();
            this.options = options;
            this.domain = options.domain;
            this.version = options.version || 'drupal-7';
            this.static = false;
            this.standalone = options.standalone || false;
            this.base_path = options.base_path || '/';
            this.protocol = options.protocol || '';
            this.baseUrl = $window.Drupal.settings.baseUrl = this.protocol + '//' + this.domain + this.base_path;
            if ("withCredentials" in new XMLHttpRequest) { this.cors = true; };
            this.initResources();
            if (this.version === 'drupal-7') { //todo: deprecated
                this.drupal = new $window.ServiceDrupal7({
                    cors: this.cors,
                    baseURL:this.baseUrl,
                    domain: this.domain,
                });
            }
            if(AppService.isOnline()) {
                this.paramsGet().then(function(params){
                    defer.resolve(params);
                })
            }else{
                defer.resolve();
            }
            return defer.promise;
        };

        this.login = function(user,pass){
            var username = user || this.default_user;
            var password = pass || this.default_pass;
            var defer = $q.defer();
            var self = this;
            $.ajax({
                type: "POST",
                data: {username: username,password: password },
                url: self.baseUrl + "?q=rest/user/login",
                dataType: "json",
                contentType: "application/x-www-form-urlencoded",
                success: function (data) {
                    $cookies[data.session_name] = data.sessid;
                    self.sessionQuery = data.session_name + '=' + data.sessid;
                    $http.defaults.headers.common['DrupalCookie'] = self.sessionQuery;
                    $.ajaxSetup({
                        beforeSend: function(request) {
                            request.setRequestHeader('DrupalCookie',self.sessionQuery);
                        }
                    });
                    self.user = data.user;
                    self.sessid = data.sessid;
                    self.session_name = data.session_name;
                    self.getToken().then(function(token) {
                        console.log('login success');
                        defer.resolve(data);
                    });
                },
                error: function (data) {
                    console.log('login error');
                    console.log(data);
                }
            });
            return defer.promise;
        };

        this.connect = function() {
            var defer = $q.defer();
            var self = this;
            $.ajax({
                type: "POST",
                url: self.baseUrl + "?q=rest/system/connect",
                dataType: "json",
                contentType: "application/x-www-form-urlencoded",
                success: function(data) {
                    //$cookies[data.session_name] = data.sessid;
                    self.sessionQuery = data.session_name + '=' + data.sessid;
                    $http.defaults.headers.common['DrupalCookie'] = self.sessionQuery;
                    $.ajaxSetup({
                        beforeSend: function(request) {
                            request.setRequestHeader('DrupalCookie',self.sessionQuery);
                        }
                    });
                    self.user = data.user;
                    self.sessid = data.sessid;
                    self.session_name = data.session_name;
                    defer.resolve(data)
                }
            });
            return defer.promise;
        };

        this.nodeGet = function(options,callback){
            var _this = this;
            var cache = options.cached || true;
            if(this.model.nodes[options.nid] && cache == true){
                return this.model.nodes[options.nid];
            }else{
                return this.Node.get({nid:options.nid},function(result){
                    _this.model.nodes[options.nid] = result;
                    if(callback){
                        callback.call(_this,result)
                    }
                })
            }
        };
        // fixme: promise resolve
        this.nodeUpdate = function(options,callback){
            var defer = $q.defer();
            var _this = this;
            this.Node.update(options.node,function(result){
                 _this.Node.get({nid:result.nid},function(node){
                     _this.model.nodes[node.nid] = node;
                     defer.resolve(node); // fixme:
                     if(callback){
                        callback.call(_this,node)
                     }
                })
            });
            return defer.promise;
        };
        this.nodeDelete = function(options,callback){
            var _this = this;
            this.Node.delete({nid:options.nid},function(){
                if( _this.model.nodes[options.nid]){
                    _this.model.nodes[options.nid] = undefined;
                }
                if(callback){
                    callback.call(_this,options.nid);
                }
            })
        };
        this.nodesGet = function(nids){
            return this.entitiesGet('node',nids);
        };
        this.nodesQuery = function(params) {
            var defer = $q.defer();
            var query = '';
           // var query = '?pagesize=200&';
            var _this = this;
            for(var k in params){
                query+='parameters['+k+']='+params[k]+'&';
            };
            $http.get(this.baseUrl+'?'+query+'q=rest/node.json').success(function(result){
                var nids = [];
                angular.forEach(result,function(node){
                   nids.push(node.nid);
                });
                _this.nodesGet(nids).then(function(result){
                    defer.resolve(result);
                })
            }).error(function(){console.log(arguments)});
            return defer.promise;
        };
        this.entitiesGet = function(type,ids){
            var defer = $q.defer();
            var _this = this;
            $http.get(this.baseUrl + '?q=rest/app_entities/node/'+encodeURI(ids)+'.json').then(function(result){
                if(type=='node') {
                    angular.forEach(result.data, function (node) {
                        _this.model.nodes[node.nid] = node;
                    })
                }
                defer.resolve(result.data);
            })
            return defer.promise;
        };
        this.menuGet = function(options,callback){
            var _this = this;
            return this.Menu.get({mid:options.mid},function(result){
                _this.model.menus[options.mid] = result;
                if(callback){
                    callback.call(_this,result)
                }
            })
        };
        this.paramsGet= function() {
            var defer = $q.defer();
            var _this = this;
            $http.get(this.baseUrl+'?q=rest/app_params.json').then(function(result){
                _this.model.siteParams = result.data;
                _this.file_directory_path = _this.baseUrl + result.data.file_directory_path;
                defer.resolve(result.data);
            })
            return defer.promise;
        };
        this.getToken = function(){
            var defer = $q.defer();
            var _this = this
            $http.get(this.baseUrl + '?q=services/session/token').then(function(token){
                _this.token = token.data;
                //$cookies['token_'+_this.domain] = token.data;
                $http.defaults.headers.common['X-CSRF-Token'] = token.data;
                $.ajaxSetup({
                    beforeSend: function(request) {
                        request.setRequestHeader("X-CSRF-Token",token.data);
                    }
                });
                defer.resolve(token)
            })
            return defer.promise;
        }

        this.initResources = function(){
            this.Node = $resource(this.baseUrl + '?q=rest/node/:nid.json', {}, {
                create: { method: 'POST',withCredentials:true,isArray:false,url:this.baseUrl + '?q=rest/node.json' },
                get: { method: 'GET',isArray:false,url:this.baseUrl + '?q=rest/node/:nid.json'},
                update: { method: 'POST',withCredentials:true,isArray:false,url:this.baseUrl + '?q=rest/node/:nid.json' },
                delete: { method: 'DELETE',withCredentials:true,isArray:true,url:this.baseUrl + '?q=rest/node/:nid.json'}
            });
            this.Node.prototype.update = function(node) {
                return this.Node.update({nid:this.nid},angular.extend({},this,{nid:undefined}),node);
            };
            this.Comment = $resource(this.baseUrl + '?q=rest/comment/:cid.json', {}, {
                get: { method: 'GET',isArray:false },
                update: { method: 'POST',isArray:false }
            });
            this.Comment.prototype.update = function (comment) {
                return this.Comment.update({cid: this.cid}, angular.extend({}, this, {cid: undefined}), comment);
            };
            this.Comments = $resource(this.baseUrl + '?:query&q=rest/comment.json', {}, {
                // ?pagesize=200 // todo:
                get: {method: 'GET',isArray:true}
            });
            this.Menu = $resource(this.baseUrl + '?q=rest/menu/:mid.json', {}, {
                get: { method: 'GET',isArray:false },
            });
            this.TaxonomyVocabulary = $resource(this.baseUrl + '?parameters[vid]=:vid&q=rest/taxonomy_vocabulary.json', {}, {
                get: {method:'GET',isArray:true,url:this.baseUrl + '?parameters[vid]=:vid&q=rest/taxonomy_vocabulary.json' },
            });
            this.TaxonomyTerm = $resource(this.baseUrl + '?parameters[tid]=:tid&q=rest/taxonomy_term.json', {}, {
                get: {method: 'GET',isArray:true},url:this.baseUrl + '?parameters[tid]=:tid&q=rest/taxonomy_term.json'
            });
            this.Views = $resource(this.baseUrl + '?:view_arguments&q=rest/views/:view_name.json', {}, {
                get: {
                    method: 'GET',
                    isArray:true,
                    withCredentials:true,
                    url: this.baseUrl + '?:view_arguments&q=rest/views/:view_name.json'
                }
            });
            this.SystemConnect = $resource(this.baseUrl + '?q=rest/system/connect.json', {}, {
                post: {
                    method: 'POST',
                    withCredentials:true,
                    isArray:true,
                    params:{},
                    headers: {'Content-Type':'application/x-www-form-urlencoded','X-CSRF-Token': this.token}
                }
            });
        }

        this.initDrupalApp = function(domain,app_nid,callback){
            var _this = this;
            var config_file;
            AppSettings.drupal.baseUrl = this.baseUrl;
            if(AppSettings.drupal.standalone == true){
                AppSettings.drupal.baseUrl = "";
            }
            if(AppSettings.drupal.static){
                config_file = AppSettings.drupal.baseUrl+AppSettings.drupal.path_to_data+'/'+app_nid+'-appsettings.jsonp';
            }else{
                config_file = AppSettings.drupal.baseUrl+'?q=appsettings/'+app_nid; // live appsettings
            }
            AppSettings.get(config_file).then(function(settings){
                var data_file;
                _this.init({domain:domain}).then(function(){
                    _this.static = settings.static;
                    console.log('update: '+settings.changed+ ' > '+ Number(localStorage.getItem('app-'+app_nid+'-json-changed')));
                    if(settings.changed > Number(localStorage.getItem('app-'+app_nid+'-json-changed')) || localStorage.getItem('app-'+app_nid+'-json-changed') == null){
                        if(settings.static == true){
                            data_file = settings.path_to_data+'/'+settings.app_nid+'-data.jsonp'; // static data update
                        }else{
                            data_file = AppSettings.drupal.baseUrl+'?q=app/'+settings.app_nid; // live data update
                        }
                        if(settings.standalone == true && settings.static == true){
                            _this.path_to_data=settings.path_to_data.replace(AppSettings.drupal.baseUrl,'')
                            AppSettings.drupal.baseUrl = '';
                            data_file = settings.path_to_data+'/'+app_nid+'-data.jsonp';
                        }else{
                            _this.file_directory_path = AppSettings.drupal.baseUrl+settings.file_directory_path
                        }
                        console.log('loading data update: ... : '+data_file) // localStorage update
                        _this.getStaticApp(data_file,function(data){
                            callback.call(_this,data);
                        })
                    }else{
                        console.log('model up to date: using localStorage');
                        _this.model =  JSON.parse(localStorage.getItem('app-'+app_nid+'-json'));
                        callback.call(_this,_this.model);
                    }
                })
            });
        },
        this.getStaticApp = function(jsonUrl,callback) {
            var _this = this
            AppData.getJSONP(jsonUrl).then(function(data){
                _this.model = _this.data  = data // fixme: scope
                // add views nodes to nodes object
                for(var k in data.views){
                    if(k=='taxonomy_term'){
                        for(var n in data.views[k]){
                            for(var nn in data.views[k][n]){
                                _this.model.nodes[data.views[k][n][nn].nid] = data.views[k][n][nn]
                            }
                        }
                    }else{
                        for(var n in data.views[k]){
                            _this.model.nodes[data.views[k][n].nid] = data.views[k][n]
                        }
                    }
                }
                _this.saveLocalModel(_this.model,'app-'+data.appSettings.app_nid);
                return callback.call(_this,_this.model);
            });
        },
        //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',AppService.getTimeStamp());
        //        if(model.appSettings.changed){
        //            $window.localStorage.setItem(id+'-json-changed',model.appSettings.changed);
        //        }
        //        console.log("saveLocalModel() :: "+id+" :: "+ $window.localStorage.getItem(id+'-json-changed') )
        //    }
        //},


        this.queryNodes= function(params,callback) {
            var query = '';
            for(var k in params){
                query+='c['+k+']='+params[k]+'&';
            };
            $http.get(this.baseUrl+'?'+query+'q=rest/node.json').success(callback).error(function(){console.log(arguments)});
        };
        this.getTaxonomyTree = function(vid,callback,maxDepth){
            var data = $.param({vid:vid,maxDepth:maxDepth||10});
            $http.post(this.baseUrl+'?q=rest/taxonomy_vocabulary/getTree.json', data,{headers: {'Content-Type': 'application/x-www-form-urlencoded','X-CSRF-Token': this.token}}
            ).success(callback);
        }
        //this.getTaxonomyTermNodes = function(tid){
        //     return this.Views.get({view_name:taxonomy_term,view_arguments:'args[0]='+tid});
        //}
        this.getParams= function(callback) {
            var _this = this
            this.drupal.service('site.getParams', {token:this.token}, function(data){ // todo: use promise
                _this.model.siteParams = data
                return callback.call(this,data);
            })
        }
        this.getNode= function(nid,callback) {
            var _this = this
            this.drupal.service('node.get', {nid:nid,token:this.token}, function(data){ // todo: use promise
                _this.model.nodes[data.nid] = data;
                return callback.call(this,data);
            })
        }
        this.getNodes= function(nids,callback) {
            var _this = this
            this.drupal.service('site.getNodes', {nids:nids}, function(data){ // todo: use promise
                for(var k in data){
                    _this.model.nodes[data[k].nid]=data[k]
                }
                return callback.call(this,data);
            })
        }

        // todo: old - remove
        this.initialize = function(options){
            var _this = this;
            var onReady = function(){
                if(options.callback){
                    return options.callback.call();
                }
            }
            this.options = options;
            this.domain = options.domain;
            this.version = options.version || 'drupal-7';
            this.static = false;
            this.base_path = options.base_path || '/';
            this.baseUrl = $window.Drupal.settings.baseUrl = 'http://' + this.domain + this.base_path;
            if ("withCredentials" in new XMLHttpRequest) { this.cors = true; };
            if(!this.drupal){ // todo: remove
                if (_this.version === 'drupal-7') {
                    _this.drupal = new $window.ServiceDrupal7({
                        cors: _this.cors,
                        baseURL: "http://" + _this.domain + _this.base_path,
                        domain: _this.domain,
                    });
                    onReady();
                }
            }else{
                onReady();
            }
        }
        //todo: end of old-remove

    }])

//.config(["$http","$httpProvider","AppSettings", function($http,$httpProvider,AppSettings) {
//        alert(AppSettings.drupal.baseUrl)
//     $http.get(AppSettings.drupal.baseUrl+'?q=services/session/token').then(function(token){
//         $httpProvider.defaults.headers.common['X-CSRF-Token'] = token;
//         $httpProvider.defaults.headers.common['X-ANGULARJS'] = 1;
//     })
//}])

    /*

    // todo: old: delets
    .factory('Node', ['$resource','$window','DrupalService', function($resource,$window,DrupalService) {
        var Node = $resource($window.Drupal.settings.baseUrl + '?q=rest/node/:nid.json', {}, {
            get: { method: 'GET',isArray:false,headers:{ 'X-CSRF-Token': DrupalService.token }}, // FIXME: DrupalService undefined
            update: { method: 'PUT',isArray:false }
        });
        Node.prototype.update = function (node) {
            return Node.update({nid: this.nid}, angular.extend({}, this, {nid: undefined}), node);
        };
        return Node;
    }])
    .factory('Nodes', ['$resource','$window','DrupalService', function($resource,$window,DrupalService){ //FIXME: DrupalService undefined
        var Nodes = $resource($window.Drupal.settings.baseUrl + '?:query&q=rest/node.json', {}, {
            get: {method: 'GET',isArray:true,headers:{ 'X-CSRF-Token': DrupalService.token }}
        });
        return Nodes;
    }])

    .factory('Comment', ['$resource','$window','DrupalService', function($resource,$window,DrupalService) {
        var Comment = $resource($window.Drupal.settings.baseUrl + '?q=rest/comment/:cid.json', {}, {
            get: { method: 'GET',isArray:false,headers:{ 'X-CSRF-Token': DrupalService.token }}, // FIXME: DrupalService undefined
            update: { method: 'PUT',isArray:false }
        });
        Comment.prototype.update = function (comment) {
            return Comment.update({cid: this.cid}, angular.extend({}, this, {cid: undefined}), comment);
        };
        return Comment;
    }])
    .factory('Comments', ['$resource','$window','DrupalService', function($resource,$window,DrupalService){
        var Comments = $resource($window.Drupal.settings.baseUrl + '?:query&q=rest/comment.json', {}, {
            get: {method: 'GET',isArray:true,headers:{ 'X-CSRF-Token': DrupalService.token }}
        });
        return Comments;
    }])

    .factory('Views', ['$resource','$window','DrupalService', function($resource,$window,DrupalService){
        var Views = $resource($window.Drupal.settings.baseUrl + '?:view_arguments&q=rest/views/:view_name.json', {}, {
            get: {
                method: 'GET',
                isArray:true,
                withCredentials:true,
                url: $window.Drupal.settings.baseUrl + '?:view_arguments&q=rest/views/:view_name.json',
                headers:{
                    'X-CSRF-Token': DrupalService.token,
                    'DrupalCookie': DrupalService.sessionQuery,
                }
            }
        });
        return Views;
    }])

    .factory('TaxonomyVocabulary', ['$resource','$window','DrupalService', function($resource,$window,DrupalService) {  // fixme: DrupalService undefined
        var TaxonomyVocabulary = $resource($window.Drupal.settings.baseUrl + '?parameters[vid]=:vid&q=rest/taxonomy_vocabulary.json', {}, {
            get: {method:'GET',isArray:true },
            headers:{
                'X-CSRF-Token': DrupalService.token
            }
        });
        return TaxonomyVocabulary;
    }])

    .factory('TaxonomyTerm', ['$resource','$window','DrupalService', function($resource,$window,DrupalService) {
        var TaxonomyTerm = $resource($window.Drupal.settings.baseUrl + '?parameters[tid]=:tid&q=rest/taxonomy_term.json', {}, {
            get: {method: 'GET',isArray:true},
            headers:{
                'X-CSRF-Token': DrupalService.token
            }
        });
        return TaxonomyTerm;
    }])

    .factory('SystemConnect', ['$resource','$window','DrupalService', function($resource,$window,DrupalService) {
        var SystemConnect = $resource($window.Drupal.settings.baseUrl + '?q=rest/system/connect.json', {}, {
            post: {
                method: 'POST',
                withCredentials:true,
                isArray:true,
                params:{},
                headers: {'Content-Type':'application/x-www-form-urlencoded','X-CSRF-Token': DrupalService.token}
            }
        });
        return SystemConnect;
    }])

*/


    // TODO: add ng_app module service
    /*
     .service('BlockService',['$http','$cookies','$q','$resource','$rootScope','$window','AppSettings','AppService','DrupalService',function($http,$cookies,$q,$resource,$rootScope,$window,AppSettings,AppService,DrupalService) {
     this.scopes = {};
     this.ready = false;
     this.init = function(scope){
     var _this = this;
     var defer = $q.defer();
     this.scopes[scope.delta] = scope;
     if(this.ready==true){
     defer.resolve();
     }else{
     console.log('BlockService: init');
     AppSettings.domain = $rootScope.ng_app_domain;
     AppSettings.drupal.baseUrl = "http://"+$rootScope.ng_app_domain+"/";
     AppService.initialize({config_file: $rootScope.ng_app_config_file,scope:$rootScope}).then(function(){
     DrupalService.init({domain:$rootScope.ng_app_domain}).then(function(){
     DrupalService.connect().then(function(){
     if(AppSettings.ng_app_blocks){
     _this.blocks = [];
     var ng_app_blocks = AppSettings.ng_app_blocks;
     for(var k in ng_app_blocks){
     for(var kk in ng_app_blocks[k]){
     _this.blocks.push(ng_app_blocks[k][kk]);
     $window.Drupal.settings[kk]={};
     $window.Drupal.settings[kk].model=ng_app_blocks[k][kk];
     }
     }
     }
     $rootScope.$broadcast("init",$rootScope);
     console.log('BlockService: resolve');
     _this.ready = true;
     defer.resolve();
     })
     })
     });
     }
     return defer.promise;
     }
     }])

     */


;

//
// to do: remove backbone legacy code
//
(function() {
    var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
    var ServiceDrupal7 = (function() {
        function ServiceDrupal7(options) {
            self = this; // fixme: global var
            this.token = options.token;
            $.ajaxSetup({
                beforeSend: function (request) {
                    request.setRequestHeader("X-CSRF-Token",options.token);
                }
            });
            this.getJSONP = __bind(this.getJSONP, this);
            this.getJSON = __bind(this.getJSON, this);
            this.options = options;
            this.cors = options.cors;
            this.gateway = options.gateway;
            this.proxy = options.proxy;
            this.domain = options.domain;
            this.sessid;
            this.user;
        }
        ServiceDrupal7.prototype.service = function(service_method, args, success, error) {
            var path, type;
            if (error == null) {
                error = this.onServiceError;
            }
            path = '';
            switch (service_method) {
                case "node.get":
                    path = 'rest/node/' + args.nid;
                    break;
                case "menu.get":
                    path = 'rest/menu/' + args.menu_id;
                    break;
                case 'views.get':
                    path = 'rest/views/' + args.view_name;
                    break;
                case 'file.get':
                    path = 'rest/file/' + args.fid;
                    break;
                case 'entity.get':
                    path = 'app/entity/get/' + args.entity + '/' + args.id;
                    break;
                case 'entity.query':
                    path = 'app/entity/query/' + args.entity + '/' + args.query;
                    break;
                case 'site.getParams':
                    path = 'app/site/getParams';
                    break;
                case 'site.getNodes':
                    path = 'app/site/getNodes/' + encodeURI(args.nids);
                    break;
                case 'site.getBook':
                    path = 'app/book/' + args.bid;
                    break;
                case 'taxonomy.getTree':
                    path = 'app/entity/taxonomy_term/' + args.vid;
            }
            type = "jsonp";
            if (path.match("rest/")) {
                path += '.jsonp';
            }
            return this.getJSON(this.options.baseURL + '?q=' + path, success, type);
        };
        ServiceDrupal7.prototype.getJSON = function(url, callback, dataType) {
            var _this;
            if (dataType == null) {
                dataType = "json";
            }
            _this = this;
            return $.ajax({
                type: "GET",
                url: url,
                dataType: dataType,
                success: function(json) {
                    return callback.call(_this, json);
                },
                error: function(json) {
                    console.log("json load error");
                    return console.log(json);
                }
            });
        };

        ServiceDrupal7.prototype.getJSONP = function(url, callback, wrapping) {
            var _this;
            if (wrapping == null) {
                wrapping = "JsonWrapping";
            }
            _this = this;
            return $.ajax({
                url: url,
                dataType: "jsonp",
                cache: true,
                jsonpCallback: wrapping,
                success: function(result) {
                    return callback.call(_this, result);
                },
                error: function(a, b, c) {
                    console.log("jsonp load failed: " + url);
                    return window.console.log(a);
                }
            });
        };

        ServiceDrupal7.prototype.onServiceError = function(response) {
            this.error = response["data"];
            console.log("ERROR :: ServiceDrupal :: " + this.error);
            return $(this).trigger("error");
        };

        window.ServiceDrupal7 = ServiceDrupal7;
    })();
}).call(this);

