(function() {
  'use strict';

  angular
      .module('app-base')
      .service('Drupal', Drupal);

      /** @ngInject */
      function Drupal($http,$rootScope,$q,$log,$resource,$window,$filter,$cookies,AppService,AppSettings){
          this.model = this.data = {
              entities:{},
              nodes:{},
              views:{},
              menus:{},
              siteParams:{}
          };
          this.sites = {};
          this.version = 'drupal-8';
          this.default_pass = '9+4v2Fvm32/8bke';
          this.default_user = 'services';
          this.token_hash = 'ff4a52397b73edb1568dd93913fea8e56f81f988a89be62a3ed953767e11c920697e1ae4c2913133d8c25139c60517d683e6ba4dd21e324f3d2cf0cd1d15abf1';
          if($window.Drupal){
              if($window.Drupal.url.isLocal()) {
                  this.isLocal = true;
              }
          }
          $window.Drupal = $window.Drupal || {};
          $window.Drupal.app_server_model = this.model;
          $window.Drupal.settings = $window.Drupal.settings || {}; // drupal-7
          $window.drupalSettings = $window.drupalSettings || {}; // drupal-8

          this.init = function(options){
              var defer = $q.defer();
              this.options = options;
              if(options.version){
                  this.version = options.version
              }
              this.domain = options.domain;
              this.static =  options.static || false;
              this.cache = options.cache || true;
              this.standalone = options.standalone || false;
              this.base_path = options.base_path || '/';
              this.protocol = options.protocol || 'http:';
              this.sites[this.domain] = {};
              this.baseUrl = $window.Drupal.settings.baseUrl = this.protocol + '//' + this.domain + this.base_path;
              this.file_directory_path = options.file_directory_path || 'sites/default/files';
              this.file_directory_path = this.baseUrl + this.file_directory_path;
              if ("withCredentials" in new XMLHttpRequest) {
                  this.cors = true;
              }
              this.initResources(this.version);
              this.initApi(this.version);
              if(AppService.isOnline() && this.static != "true") {
                  this.getParams().then(function(params){
                      $rootScope.$broadcast('init-drupal');
                      defer.resolve(params);
                  })
              }else{
                  $rootScope.$broadcast('init-drupal');
                  defer.resolve();
              }
              return defer.promise;
          };

          this.connect = function() {
              var defer = $q.defer();
              var self = this;
              // fixme: drupal-8 + use SystemConnect resource, remove jquery dependency
              $.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.login = function(user,pass){
              var username = user || this.default_user;
              var password = pass || this.default_pass;
              var defer = $q.defer();
              var self = this;
              var url;
              if(self.version === 'drupal-8'){
                  url = 'index.php/user/login';
              }
              if(self.version === 'drupal-7'){
                  url = '?q=rest/user/login';
              }
              // fixme: use $http service
              $.ajax({
                  type: "POST",
                  data: {username: username,password: password },
                  url: self.baseUrl + url,
                  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) {
                          $log.log('login success');
                          defer.resolve(data);
                      });
                  },
                  error: function (data) {
                      $log.error('login error');
                      $log.log(data);
                  }
              });
              return defer.promise;
          };

          this.initApi = function(version){
              var _this = this;
              this.node = function(){};
              this.node.get = function(options,succes){
                  var defer = $q.defer();
                  var cache = _this.cache;
                  if(_this.model.nodes[options.nid] && cache === true){
                      if(succes){
                        succes.call(null,_this.model.nodes[options.nid]);
                      }
                      defer.resolve(_this.model.nodes[options.nid]);
                  }else{
                      return _this.Node.get({nid:options.nid},function(result){
                          if(result.uuid && typeof result.uuid === "string") {
                              _this.setEntity(result.uuid, result); // drupal-7
                          }
                          if(result.uuid && result.uuid && typeof result.uuid !== "string") {
                              _this.setEntity(result.uuid[0].value, result); // drupal-8
                          }
                          _this.model.nodes[$filter('nid')(result)] = result;
                          if(succes){
                            succes.call(null,result);
                          }
                          defer.resolve(result);
                      })
                  };
                  return defer.promise;
              };
              this.node.save = function saveNode(node,succes){
                  if(node.nid) {
                      _this.Node.update(node,function(res){
                          succes.call(this,res);
                      },function(err){
                      })
                  }else{
                      _this.Node.create(node,function(res){
                          succes.call(this,res);
                         // defer.resolve(res);
                      },function(err){
                         // defer.resolve(res);
                      })
                  }
              };
              this.menu = function(){};
              this.menu.get = function(options,succes){
                  return _this.Menu.get(options,function(result){
                      _this.model.menus[options.mid] = result;
                      succes.call(this,result);
                  });
              };
              this.views = function(){};
              this.views.get = function(options,succes){
                  var defer = $q.defer();
                  return _this.Views.get(options,function(result){
                      _this.model.views[options.view_name] = result;
                      if(succes){
                          succes.call(null,result);
                      }
                      defer.resolve(result);
                  });
                  return defer.promise;
              };
//            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;
          };

          this.initResources = function(version){
              var pre, url, urlPost, trail;

              if(version === 'drupal-7'){
                  pre = '?q=';
                  url = 'rest/node';
                  urlPost = 'rest/node';
                  trail = '.json';
              }
              if(version === 'drupal-8'){
                  pre = 'index.php/';
                  url = 'node';
                  urlPost = 'entity/node';
                  trail = '?_format=hal_json';
                 // trail = '?_format=json';
              }
              // node resource
              this.Node = $resource(this.baseUrl + pre + url + '/:nid' + trail, {}, {
                  create: { method: 'POST',withCredentials:true,isArray:false,url:this.baseUrl + pre + urlPost + '' + trail },
                  get: { method: 'GET',isArray:false,url:this.baseUrl + pre + url + '/:nid' + trail},
                  update: { method: 'POST',withCredentials:true,isArray:false,url:this.baseUrl + pre + url + '/:nid' + trail },
                  delete: { method: 'DELETE',withCredentials:true,isArray:true,url:this.baseUrl + pre + url + '/:nid' + trail}
              });
              this.Node.prototype.update = function(node) {
                  //return this.Node.update({nid:$filter('nid')(this)},angular.extend({},this,{nid:undefined}),node);
                  return this.Node.update({nid:this.nid},angular.extend({},this,{nid:undefined}),node);
              };

              // views resource
              var path;
              if(version === 'drupal-7'){
                  path = this.baseUrl + '?:view_arguments&q=rest/views/:view_name';
              }
              if(version === 'drupal-8'){
                  path = this.baseUrl + pre + 'rest/views/:view_name';
              }
              this.Views = $resource(path + trail, {}, {
                  get: {
                      method: 'GET',
                      isArray:true,
                      withCredentials:true,
                      url: path + trail
                  }
              });

              // comment resource
              this.Comment = $resource(this.baseUrl + '?q=rest/comment/:cid' + trail, {}, {
                  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' + trail, {}, {
                  // ?pagesize=200 // todo:
                  get: {method: 'GET',isArray:true}
              });


              this.Menu = $resource(this.baseUrl + '?q=rest/menu/:mid' + trail, {}, {
                  get: { method: 'GET',isArray:false },
              });

              this.TaxonomyVocabulary = $resource(this.baseUrl + '?parameters[vid]=:vid&q=rest/taxonomy_vocabulary' + trail, {}, {
                  get: {method:'GET',isArray:true,url:this.baseUrl + '?parameters[vid]=:vid&q=rest/taxonomy_vocabulary' + trail },
              });
              this.TaxonomyTerm = $resource(this.baseUrl + '?parameters[tid]=:tid&q=rest/taxonomy_term' + trail, {}, {
                  get: {method: 'GET',isArray:true},url:this.baseUrl + '?parameters[tid]=:tid&q=rest/taxonomy_term' + trail
              });

              this.SystemConnect = $resource(this.baseUrl + '?q=rest/system/connect' + trail, {}, {
                  post: {
                      method: 'POST',
                      withCredentials:true,
                      isArray:true,
                      params:{},
                      headers: {'Content-Type':'application/x-www-form-urlencoded','X-CSRF-Token': this.token}
                  }
              });

              // custom: drupal 7
              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' + trail).success(callback).error(function(){$log.log(arguments)});
              };

              this.getTaxonomyTree = function(vid,callback,maxDepth){
                  var data = $.param({vid:vid,maxDepth:maxDepth||10});
                  $http.post(this.baseUrl+ pre + 'rest/taxonomy_vocabulary/getTree' + trail, data,{headers: {'Content-Type': 'application/x-www-form-urlencoded','X-CSRF-Token': this.token}}
                  ).success(callback);
              };
          };

          //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' + trail).success(callback).error(function(){$log.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' + trail, data,{headers: {'Content-Type': 'application/x-www-form-urlencoded','X-CSRF-Token': this.token}}
          //    ).success(callback);
          //};

          this.getParams = function() {
              var defer = $q.defer();
              var _this = this;
              var url = 'index.php/rest/params?_format=hal_json';
              if(_this.version === 'drupal-7'){
                  url = '?q=rest/app_params.json';
              }
              $http.get(this.baseUrl+url).then(function(result){
                  if(result.status == 200) {
                      _this.model.siteParams = result.data;
                      defer.resolve(result.data);
                  }else{
                      $log.error("Rest resource 'params' on "+_this.domain+" is not available.");
                      $log.log(result);
                      defer.resolve(result);
                  }
              });
              return defer.promise;
          };

          this.getToken = function(){
              var defer = $q.defer();
              var _this = this;
              var url;
              if(_this.version === 'drupal-8'){
                  url = this.baseUrl + 'index.php/rest/session/token?_format=hal_json';
              }
              if(_this.version === 'drupal-7'){
                  url = this.baseUrl + '?q=services/session/token';
              }
              $http.get(url).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.setEntity = function(uuid,value) {
              this.model.entities[uuid] = value;
          };
          this.getEntity = function(uuid) {
              if(this.model.entities[uuid]){
                  return this.model.entities[uuid];
              }
          };
          //this.setFieldEntities = function(el){
          //    var _this = this;
          //    el.find("div[data-quickedit-field-id]").each(function(i,el){
          //        var entity = {};
          //        var uuid = AppService.getUUID();
          //        var field = el;
          //        var data = angular.element(field).attr('data-quickedit-field-id').split('/');
          //        var field_type = data[2];
          //        var field_class = 'field--name-'+field_type.replace('_','-');
          //        angular.element(field).addClass(field_class);
          //
          //        entity['type'] = 'field';
          //        entity['field_type'] = field_type;
          //        entity['field_class'] = field_class;
          //        entity['field_context'] = data;
          //        entity['element'] = field;
          //
          //        _this.setEntity(uuid,entity)
          //    })
          //};
          // todo: ??
          this.getEntityId = function(uuid) {
              if(this.model.entities[uuid]){
                  var arr = this.model.entities[uuid]._links.self.href.split('/');
                  return arr[arr.length-1].split('?')[0];
              }
          };


          //this.checkRestServer = function(url){
          //    var request;
          //    if($window.XMLHttpRequest)
          //        request = new XMLHttpRequest();
          //    else
          //        request = new ActiveXObject("Microsoft.XMLHTTP");
          //    request.open('GET',url , false);
          //    request.send(); // there will be a 'pause' here until the response to come.
          //    if (request.status === 404) {
          //        $log.error("Rest resource 'params' on "+this.domain+" is not enabled.");
          //    }
          //}

      }

})();
