/**
 * Created by shadeeka on 12/6/15.
 */
angular.module('app.services')
  .filter('isPending', function(){
    return function(object) {
      var visibleUser = false;
      for(var key in object) {
        if(object[key]== "pending") {
          visibleUser = true;
          break;
        }
      }
      return visibleUser;
    };
  })
  .factory('initService', ['$log', '$timeout', '$q', '$http','$filter', 'dataPersistenceService', '$interval', 'sparkDataService', 'preConditions',"issuesCache","$cordovaNetwork","Util","propertyCache","$ionicHistory","$state",
    function ($log, $timeout, $q, $http,$filter, dataPersistenceService, $interval, sparkDataService ,preConditions,issuesCache, $cordovaNetwork, Util,propertyCache,$ionicHistory,$state) {
    var cache;
    var sync_in_progress = false;
    var syncRecordCount = 0;
    var syncRetryCount = 0;
    var syncMaxRetryCount = 15;//2.5 minutes wating time to retry next sync
    var syncMaxRetryCountWhenNotResponding = 30;//10 minutes wating time to retry next sync
    var checkIntervalInterval="";
    var syncInProgressRecords ={};
    var midNightPerformed=false;
    return {

      init: function () {

        Util.setIpAddress();
        Util.setMacAdress();

        if($cordovaNetwork.isOnline()==true){
          Util.setNetworkStatus('online');
        }else{
          Util.setNetworkStatus('offline');
        }


        //init database here
        dataPersistenceService.init();

        //check applications status
        dataPersistenceService.selectApplicationStatus().then(function (result) {
          cordova.plugins.autoStart.disable();
        }, function (result) {
          cordova.plugins.autoStart.enable();
        });

        issuesCache.init();

        //get session plans for this module
        sparkDataService.getSessionPlans();

        sparkDataService.getSiluhoutteNames();

        sparkDataService.getStyles();

        //load session plans for the cache
        preConditions.loadSessionPlans();

        preConditions.loadSiluhouttes();

        //check configurations
        preConditions.checkPreValidations();
        sparkDataService.syncDailyCounts();
        //check day start
        //if(preConditions.checkPreValidations()){
        //  console.log("Configuration availability 0-----------> ");
        //  preConditions.isAvailableDayStart();
        //}

        //start sync operation
        this.synchronize();

        this.synchronizeOperations();

        this.loadStartedData();
      },

      loadStartedData: function () {
        console.debug("load started styles ........ ");

        dataPersistenceService.selectDayStart().then(function (result) {
          $log.debug("Day Start result");
          $log.debug(result);

          for (var i = 0; i < result.rows.length; i++) {
            if(result.rows.item(i).Key == "style"){
              $log.debug(result.rows.item(i).Key, result.rows.item(i).Value);
              propertyCache.setSelectedStyles(result.rows.item(i).Value);
            }
          }
        }, function (result) {
          $log.debug("day start go to day start view [error]");
        });

      },

      loadInitialData: function () {
        console.debug("loadInitialData........ ");
        var deferred = $q.defer();
        //go to database

        var allDaiyCountPr = dataPersistenceService.selectAllTheDailyCount();
        allDaiyCountPr.then(function (result) {
          console.debug("loadInitialData........ success ");
          var _self = this;
          var countData = [];
          for (var i = 0; i < result.rows.length; i++) {
            var data = new Object();
            data.name = result.rows.item(i).Type;
            data.count = result.rows.item(i).Count;
            countData.push(data);
            console.log(result.rows.item(i).Type + " : " + result.rows.item(i).Count);
          }
          deferred.resolve(countData);
        },function(err){
          deferred.reject();
          console.log("Error in Getting counts from DB !" , err);
          console.debug("loadInitialData........ error ");
        })

        //return them as an array
        return deferred.promise;
      },


      synchronize: function () {
        var _self = this;
        $interval(function () {
          _self.logOutMidNight();
        }, 10000);
        $interval(function () {
          _self.syncRealTime(false);
        }, 1000*60*5);//resync network check
      },

      synchronizeOperations: function () {
        //sparkDataService.getOperationsForStyles();
      },



      syncRealTime: function (needResync) {
        $log.info("syncRealTime .. "+sync_in_progress);
        var _self = this;
        if (sync_in_progress) {
          return;
        }

        $log.info("start resync.... ");

        dataPersistenceService.selectNetworkFaliure().then(function (result) {
          syncRecordCount=result.rows.length;
          for (var i = 0; i < result.rows.length; i++) {
            sync_in_progress = true;
            var eventToSend = new Object();
            eventToSend.id = result.rows.item(i).Id;
            eventToSend.endPoint = result.rows.item(i).EndPoint;
            eventToSend.name = result.rows.item(i).Type;
            eventToSend.data = JSON.parse(result.rows.item(i).Data);
            eventToSend.status = 'SENT';
            dataPersistenceService.updateNetworkFaliures(eventToSend);
            syncInProgressRecords[eventToSend.id] ="pending";
            sparkDataService.syncSendRecords(eventToSend).then(function (resp) {

              dataPersistenceService.removeNetworkFaliures(resp).then(function (successResult) {
                  //check all records are done sending
                  syncInProgressRecords[successResult.id]="success";
                  // _self.doCompleteSyncCycle();
                }
              );

            }, function (err) {
              syncInProgressRecords[err.id]="fail";
              eventToSend.status = 'PENDING';
              dataPersistenceService.updateNetworkFaliures(eventToSend);
              // _self.doCompleteSyncCycle();
            });

          }

          if(!needResync) {
            $timeout(function () {
              _self.checkIntervalInterval();
            }, 1000 * 60);
          }

        }, function (err) {//zero records
          if(!needResync) {
            $timeout(function () {
              _self.checkSentCount();
            }, 1000 * 60);
          }
        });
      },
      checkIntervalInterval:function(){
        var _self = this;
        if(checkIntervalInterval!=""){
          $interval.cancel(checkIntervalInterval);
        }
        checkIntervalInterval = $interval(function () {
          syncRetryCount++;
          $log.info("checkIntervalInterval....sync_in_progress "+sync_in_progress);
          $log.info("checkIntervalInterval....syncRecordCount "+syncRecordCount);
          $log.info("checkIntervalInterval....syncRetryCount "+syncRetryCount);
          $log.info("checkIntervalInterval....syncMaxRetryCount "+syncMaxRetryCount);
          $log.info("checkIntervalInterval....syncMaxRetryCountWhenNotResponding "+syncMaxRetryCountWhenNotResponding);
          var succesCount=_.groupBy(syncInProgressRecords).success;
          if(succesCount!= undefined) {
            $log.info("checkIntervalInterval....succesCount " + succesCount.length);
            if (syncRecordCount <= succesCount.length) {
              _self.checkPendingCount();
            }
          }

          if(!sync_in_progress) {
            if (syncRetryCount > syncMaxRetryCount) {
              _self.checkPendingCount();
            }
          }

          //when not responding resetting sync cycle
          if (sync_in_progress && (syncRetryCount > syncMaxRetryCountWhenNotResponding)) {
            _self.checkPendingCount();
          }

        }, 1000 * 10);
      },
      checkPendingCount:function(){
        var _self = this;
        dataPersistenceService.countNetworkFaliurePending().then(function (result) {
          $log.info("checkIntervalInterval....countNetworkFaliurePending " + result.rows.item(0).cnt);
          if(result.rows.item(0).cnt > 0) {
            _self.doCompleteSyncCycle(true);
          }else{
            _self.doCompleteSyncCycle(false);
            $interval.cancel(checkIntervalInterval);
          }
          syncRetryCount = 0;
        });
      },checkSentCount:function(){
        var _self = this;
        dataPersistenceService.countNetworkFaliurePending().then(function (result) {
          $log.info("checkIntervalInterval....countNetworkFaliurePending " + result.rows.item(0).cnt);
          if(!(result.rows.item(0).cnt > 0)) {
            dataPersistenceService.countNetworkFaliureSent().then(function (result) {
              $log.info("checkIntervalInterval....countNetworkFaliureSent " + result.rows.item(0).cnt);
              if (result.rows.item(0).cnt > 0) {
                dataPersistenceService.updateAllNetworkFaliures("PENDING");
                $timeout(function () {
                  _self.syncRealTime(false);
                }, 1000);
              } else {
                _self.doCompleteSyncCycle(false);
                $interval.cancel(checkIntervalInterval);
              }
              syncRetryCount = 0;
            });
          }
        });
      },
      doCompleteSyncCycle:function(needResync){
          var _self = this;
          sync_in_progress = false;
          syncInProgressRecords={};
          $log.info("doCompleteSyncCycle....cycle completed "+sync_in_progress);
          if(needResync) {
            _self.syncRealTime(needResync);
          }
      },logOutMidNight:function(){
        try {
          var _self = this;
          var minCount = _self.minutesUntilMidnight();
          if (minCount == 0 && !midNightPerformed) {
            $log.info("midnight detected....");
            localStorage.removeItem("today-daystart");
            propertyCache.clearCacheData();
            preConditions.setCache(false);
            var dataRemove = new Object();
            dataRemove.date = _self.getFormattedDate();
            dataPersistenceService.removeDayStartByDate(dataRemove);
            $ionicHistory.clearCache().then(function () {
              //_self.init();
            });
            $ionicHistory.clearHistory();
            $timeout(function () {//reload app after 30 seconds
              _self.restartApp();
            }, 1000 * 60);
            midNightPerformed = true;
            $state.go("login");
          }
        }catch(error){
            console.log("Logout error -----> ",error);
            $state.go("login");
        }
      },logOutMidNightStartUp:function(){
        try {
          $log.debug("logOutMidNightStartUp....");
          var _self = this;
            localStorage.removeItem("today-daystart");
            propertyCache.clearCacheData();
            preConditions.setCache(false);
            var dataRemove = new Object();
            dataRemove.date = _self.getFormattedDate();
            dataPersistenceService.removeDayStartByDate(dataRemove);
            $ionicHistory.clearCache().then(function () {
            });
            $ionicHistory.clearHistory();
        }catch(error){
          console.log("logOutMidNightStartUp error -----> ",error);
        }
      },minutesUntilMidnight:function(){
        var midnight = new Date();
        midnight.setHours( 24 );
        midnight.setMinutes( 0 );
        midnight.setSeconds( 0 );
        midnight.setMilliseconds( 0 );
        var res=parseInt(( midnight.getTime() - new Date().getTime() ) / 1000 / 60);
        $log.info("minutesUntilMidnight...."+res);
        return res;
      },restartApp:function(){
          navigator.app.exitApp();
          navigator.app.loadUrl("file:///android_asset/www/index.html", {wait:10000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 30000});
      },getFormattedDate: function () {

        var d = new Date();
        var month = '' + (d.getMonth() + 1);
        var day = '' + d.getDate();
        var year = d.getFullYear();

        if (month.length < 2)
          month = '0' + month;
        if (day.length < 2)
          day = '0' + day;
        currentDate = [year, month, day].join('.');
        return [year, month, day].join('.');
      },clearMidNightData:function(){
        console.log("clearMidNightData...");
        midNightPerformed=false;
      },

      getStylesPosColours : function (){
        sparkDataService.getStyles();
      },loadingConfigData: function (){
        console.log("loadingConfigData...");
        dataPersistenceService.selectConfigurations().then(function(result){
          for(var i =0;i<result.rows.length;i++){
            if (configData.hasOwnProperty(result.rows.item(i).Key)) {
              configData[result.rows.item(i).Key] = result.rows.item(i).Value;
            }
          }
        });
      }



    };
  }]);
