/**
 * 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", "updateService", '$resource',
    function ($log, $timeout, $q, $http, $filter, dataPersistenceService, $interval, sparkDataService, preConditions, issuesCache, $cordovaNetwork, Util, propertyCache, $ionicHistory, $state, updateService, $resource) {
      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();
          if (propertyCache.day_start["sessionPlan"] != undefined && propertyCache.day_start["sessionPlan"] != "") {
            sparkDataService.loadSessionDetail(propertyCache.day_start["sessionPlan"]);
          }
          //check day start
          //if(preConditions.checkPreValidations()){
          //  console.log("Configuration availability 0-----------> ");
          //  preConditions.isAvailableDayStart();
          //}

          //start sync operation
          this.synchronize();

          this.synchronizeOperations();

          this.loadStartedData();

          var readData = $resource("/ionic.project");
          readData.get();
        },

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

          dataPersistenceService.selectStartedStyles().then(function (result) {
            $log.debug("Day Start result");
            $log.debug(result);
            for (var i = 0; i < result.rows.length; i++) {
              propertyCache.setSelectedStyles(result.rows.item(i).Style);
            }
          }, function (result) {
            $log.debug("day start go to day start view [error]");
          });

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

            for (var i = 0; i < result.rows.length; i++) {
              if(propertyCache.day_start.hasOwnProperty(result.rows.item(i).Key)){
                if(result.rows.item(i).Date == dataPersistenceService.getFormattedDate()) {
                  $log.debug(result.rows.item(i).Key, result.rows.item(i).Value);
                  propertyCache.day_start[result.rows.item(i).Key] = result.rows.item(i).Value;
                }
              }else if(propertyCache.optional_day_start_data.hasOwnProperty(result.rows.item(i).Key)){
                if(result.rows.item(i).Date == dataPersistenceService.getFormattedDate()) {
                  $log.debug(result.rows.item(i).Key, result.rows.item(i).Value);
                  propertyCache.optional_day_start_data[result.rows.item(i).Key] = result.rows.item(i).Value;
                }
              }
            }
          }, function (result) {
            $log.debug("day start go to day start view [error]");
          });

        },

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

          if (daystartWise) {

            var eventToSend = new Object();
            eventToSend.data = {};
            eventToSend.data.so = propertyCache.day_start.key2;
            eventToSend.data.li = propertyCache.day_start.key1;
            eventToSend.data.style = propertyCache.day_start.style;

            var allDaiyCountPr = dataPersistenceService.selectStyleSoLiWiseWithoutTypeDailyCount(eventToSend);
            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 ");
            })

          } else {

            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
          $interval(function () {
            _self.chekRealtimeUpdate();
          }, 1000 * 60 * 15)
        },

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

        chekRealtimeUpdate: function () {
          $log.info("....................ChekRealtimeUpdate .. ......................");
          updateService.updateApplication(false);
        },

        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';
              if (propertyCache.factoryConfigs.count_track_mac_address != undefined && propertyCache.factoryConfigs.count_track_mac_address) {
                eventToSend.macAddress = JSON.parse(result.rows.item(i).MacAddress);
              }
              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;
              }
            }
          });
        }


      };
    }]);
