//(C) Copyright 2020 Hewlett-Packard Enterprise Company, L.P.
define(['fs/presenter/settings/DateTimeSetupPresenter',
        'hp/core/Localizer',
        'hp/core/EventDispatcher',
        'jquery',
        'lib/jquery.dateFormat',
        'lib/jquery-ui-timepicker-addon',
        'hp/lib/jquery-ui-timepicker-extension',
        'hp/lib/jquery.hpSearchCombo',
        'hp/lib/jquery.hpTimestamp',
        'lib/jquery.validate'],
function(dateTimePresenter, localizer,EventDispatcher) {"use strict";

    return ( function() {

        var NTP_SERVER_TEXT = '#cic-network-ntpserver',
            CURRENT_DATE_TIME_TEXT = '#cic-network-currentdatetimeText',
            TIMEZONE = '#cic-network-timezone',
            TIMEZONE_INPUT = '#cic-network-timezone-input',
            LOCALE = '#cic-network-locale',
            LOCALE_INPUT = '#cic-network-locale-input',
            NTP_SERVER = '.cic-network-ntpserver-group',
            CURRENT_DATE_TIME = '#cic-network-currentdatetime',
            CURRENT_DATE_TIME_LABEL_GROUP = '#cic-network-currentdatetimelabel',
            CURRENT_DATE_TIME_LABEL_VALUE= '#cic-network-currentdatetimelabelValue',
            FORM = '#cic-settings-network-form',
            TIME_SYNC_SERVER='#cic-network-syncwithserver',
            TIME_SYNC_MANUAL='#cic-network-manualdatetime',
            CURRENT_DATE_TIME_ERR_LABEL='#cic-network-currentdatetime-errors',
            HAS_ERROR = '#cic-network-form input.hp-error',
            INVALID_PARAMETER_ERROR_CODE = 'INVALID_PARAMETER',
            TIME_AND_PLACE_CHOOSER ='timeandplacechooser',
            TIME_AND_PLACE_RADIO_GRP='input[type="radio"][name='+TIME_AND_PLACE_CHOOSER+']:checked',
            DATETIME_WARNING = '#cic-datetime-warning',
            notifyFlag = false;



        var CURRENT_DATE_TIME_FORMAT='MMM d, yyyy hh:mm a',
            DATE_PICKER_FORMAT='yyyy-MM-dd HH:mm:ss';

        var MAX_NTP_SERVERS_CONFIGURABLE = 3;


        var clickEventForSync = false;
        var timeZone = "";
        var localeList = [];
        var locale_str ="" ;
        var locale_val ="" ;
        var timers = [];
        var dateTimeUnixTS = Date.parse(new Date());
        var clockUpdateTimeout = 1000;//ms
        var isManualSetting = true;

        function TimeAndPlaceView() {
          // The validator for time and place
          var validator;
          // form state view for time and place passed from network Edit base
          var formstateview;

          //dispatcher
          var dispatcher = new EventDispatcher();
           this.on = function (eventName, callback){
               dispatcher.on(eventName, callback);
           };

           this.off = function(eventName, callback) {
               dispatcher.off(eventName, callback);
           };

           /**
            * @private Displays an error notification as well as details about the error
            * @param {string} message Message containing high level error message
            * @param {string} details Message containing error details
            * @param {string} messageType indicates the type of notification such as error
            */
           function displayNotifications(message, details, type) {
               if (notifyFlag) {
                   var notif = {
                       sourceName: localizer.getString('fs.settings.network.notify.sourceName'),
                       summary : message,
                       status : 'error',
                       details : details
                   };
                   formstateview.setMessage(notif);
                   notifyFlag = false;
               }
           }

           /**
             * @private Formats error information from a REST request
             * @param errorInfo {object} Rest request error information
             * @returns {String} Formatted error information to display
             */
            function formatNotificationDetails(errorInfo) {
                var resolution = (errorInfo.recommendedActions &&
                     errorInfo.recommendedActions !== '?') ? '</br>' + errorInfo.recommendedActions : '';
                var message = (errorInfo.message && errorInfo.message !== '?') ? '</br>' + errorInfo.message : '';
                var failureNotificationDetails = message + resolution;
                return  failureNotificationDetails;
            }


            this.addValidatorOptions = function(options) {
                $.extend(true, options, {
                      messages : {
                          'ntpserver':localizer.getString('fs.settings.network.validator.ntpserver.ntp_fqdn_required'),
                          'currentdatetime':localizer.getString('fs.settings.network.validator.currentdatetime.datetime_required'),
                          'timezone_input':localizer.getString('fs.settings.network.validator.timezone.timezone_required'),
                          'locale_input': localizer.getString('fs.settings.network.validator.locale.locale_required')
                      },
                      errorClass : 'hp-error',
                      errorPlacement :  function (error, element) {
                         switch (element.attr('name')) {
                          case 'ntpserver1':
                          case 'ntpserver2':
                          case 'ntpserver3':
                              error.insertAfter(element);
                              break;
                          case 'currentdatetime':
                              error.appendTo($(CURRENT_DATE_TIME_ERR_LABEL));
                              break;
                          case 'timezone_input':
                            error.insertAfter(element.is('.hp-search-combo-input') ? element.parent() : element);
                            break;
                          case 'locale_input':
                              error.insertAfter(element.is('.hp-search-combo-input') ? element.parent() : element);
                              break;
                          default:
                              error.insertAfter(element);
                              break;
                        }

                      },
                      rules : {
                          'ntpserver1' : {
                              required : true,
                              hpTimeandlanguageNtpAddress : (NTP_SERVER_TEXT+1)
                          },
                          'ntpserver2' : {
                              hpTimeandlanguageNtpAddress : (NTP_SERVER_TEXT+2)
                          },
                          'ntpserver3' : {
                              hpTimeandlanguageNtpAddress : (NTP_SERVER_TEXT+3)
                          },
                           'currentdatetime' : {
                                required : true
                          },
                          'timezone_input' : {
                                  required : true
                        },
                        'locale_input' : {
                            required : true
                  }
                    }
                });
                return options;
            };

            /**
             * @private Add a server side error to the list of errors that the validator will display
             * @param {object} validatorErrors The list of errors that the validator will display
             * @param {object} errorFromServer The error from a REST response body to add to the list
             */
             function addValidatorError(validatorErrors, errorFromServer) {
               var errorMessage = errorFromServer.message;
               var sourceId = errorFromServer.errorSource;

               switch (sourceId) {
                 case 'ntpServer1':
                     $.extend(validatorErrors, {
                         'ntpserver1': errorMessage
                     });
                     break;
                 case 'ntpServer2':
                     $.extend(validatorErrors, {
                         'ntpserver2': errorMessage
                     });
                     break;
                 case 'ntpServer3':
                     $.extend(validatorErrors, {
                         'ntpserver3': errorMessage
                     });
                     break;
                 case 'setNTP':
                     $.extend(validatorErrors, {
                       'currentdatetime' : errorMessage
                     });
                     errorFromServer.recommendedActions =
                        localizer.getString('fs.settings.network.validator.currentdatetime.datetime_format_resolution');

                     break;
                 case 'validateTimeZone':
                   /// add time zone specific
                     $.extend(validatorErrors, {
                       'timezone_input' : errorMessage
                     });
                     break;
                 case 'setApplianceDefaultLocale':
                     /// add locale specific
                       $.extend(validatorErrors, {
                         'locale_input' : errorMessage
                       });
                       break;
                 default:
                   break;
               }
              }


             /**
              * @private Display invalid parameter errors from the server
              * @param {object} errorInfo The response body generated by a server exception
              */
             function handleParameterErrorsFromServer(errorInfo) {
                 var validatorErrors = {};
                 var serverErrorList = errorInfo.nestedErrors;
                 var serverError;
                 var handled = true;
                  if(errorInfo.errorCode == INVALID_PARAMETER_ERROR_CODE) {
                     for(serverError in serverErrorList) {
                     if(!addValidatorError(validatorErrors, serverErrorList[serverError])) {
                         handled = false;
                     }
                  }
                 }else{
                       addValidatorError(validatorErrors, errorInfo);
                       handled = false;
                 }
                 validator.showErrors(validatorErrors);
                 return handled;
             }

             /**
              * @public Handle failed validation by printing error messages
              * @param {object} errorInfo The response body generated by a server exception
              */
             function onSetConfigError(errorInfo) {
                 handleParameterErrorsFromServer(errorInfo);
                 var applyErrorMsg = localizer.getString('fs.settings.network.notify.set.error');
                 var failureNotificationDetails = formatNotificationDetails(errorInfo);
                 notifyFlag = true;
                 displayNotifications(applyErrorMsg, failureNotificationDetails, 'error');

             }
             /**
              * @private Re-validate the fields that are showing errors; leave
              * the fields without errors alone (so that we don't
              * display errors in them prematurely).
              */
             function resetFailures() {
                 $(HAS_ERROR).each(function() {
                     validator.element(this);
                 });
             }

             function registerClock(on){
                 //clear old timers
                 $.each(timers,function(index){
                     clearInterval(timers[index]);
                 });
                 timers = [];
                 if(on){
                     var updateDateTimeField;
                     var d = new Date();
                     if(isManualSetting){
                         clockUpdateTimeout = 1000;
                         updateDateTimeField = function(){
                             $(CURRENT_DATE_TIME_TEXT).val($.format.date(d, DATE_PICKER_FORMAT));
                         };
                     }else{
                         clockUpdateTimeout = 60000;
                         updateDateTimeField = function(){
                             $(CURRENT_DATE_TIME_LABEL_VALUE).text($.format.date(d, CURRENT_DATE_TIME_FORMAT));
                         };
                     }
                     //register clock
                     var clockTick = setInterval(function(){
                         dateTimeUnixTS = dateTimeUnixTS + clockUpdateTimeout;
                         d.setTime(dateTimeUnixTS);
                         updateDateTimeField();
                         if($(CURRENT_DATE_TIME_TEXT).is(':focus')){
                             $(CURRENT_DATE_TIME_TEXT).datepicker('updatePicker',d);
                         }
                     },clockUpdateTimeout);
                     //Add to timers list
                     timers.push(clockTick);
                 }
             }

             function showDateTime(data) {
                var dateVal = dateTimePresenter.parseDateTime(data);
                dateTimeUnixTS = Date.parse(new Date(dateVal));
                if(isManualSetting){
                    var textdateVal = $.format.date(dateVal, DATE_PICKER_FORMAT);
                    $(CURRENT_DATE_TIME_TEXT).val(textdateVal);
                }else{
                    var labeldateVal = $.format.date(dateVal, CURRENT_DATE_TIME_FORMAT);
                    $(CURRENT_DATE_TIME_LABEL_VALUE).text(labeldateVal);
                }
                registerClock(true);
            }

            function getDateTime() {
                dateTimePresenter.getDateTime();
            }
            function fillNTPFields(ntpServerList){
                for(var index = 0;index < MAX_NTP_SERVERS_CONFIGURABLE;index = index+1){
                    $(NTP_SERVER_TEXT+(index+1)).val((ntpServerList[index]?ntpServerList[index]:''));
                }
            }
            function checkNTPservers(data) {
                if( data.ntpServers.length > 0  ||  clickEventForSync ){
                    fillNTPFields(data.ntpServers);
                    $(TIME_SYNC_SERVER).attr('checked',true);
                    $(CURRENT_DATE_TIME_LABEL_GROUP).show();
                    isManualSetting = false;
                    getDateTime();
                    $(NTP_SERVER).show();
                    $(CURRENT_DATE_TIME).hide();
                    clickEventForSync=false;
                    $(DATETIME_WARNING).hide();
                }
                else{
                    $(TIME_SYNC_MANUAL).attr('checked',true);
                    $(NTP_SERVER).hide();
                    $(CURRENT_DATE_TIME_LABEL_GROUP).hide();
                    $(CURRENT_DATE_TIME).show();
                    $(CURRENT_DATE_TIME).val('');
                    $(DATETIME_WARNING).show();
                    isManualSetting = true;
                }
            }
            function showNTPservers(data) {
                fillNTPFields(data.ntpServers);
                checkNTPservers(data);
            }

            function showTimezone(timezoneData) {
                timeZone = timezoneData.timezoneString;
                dateTimePresenter.getTimeZones({
                    success: function(timezones) {
                        var timeZoneList = [];
                        $.each(timezones.members, function (i, data) {
                            var tempObj = {id: i, name: data};
                            timeZoneList[i] = tempObj;
                        });
                        $(TIMEZONE).hpSearchCombo({results: timeZoneList, maxResults: timeZoneList.length});
                        $(TIMEZONE).hpSearchCombo('set', {name:timeZone});
                        $(TIMEZONE_INPUT).attr('name', 'timezone_input');
                        dispatcher.fire("fieldUpdated",true);
                    },
                    error: function (){
                 }});
            }

            function showLocale(localeData)
            {
                var system_locale_name = localeData.displayName;
                var system_locale = "en_US.UTF-8";
                dateTimePresenter.getLocales({
                    success: function(locales) {

                        $.each(locales.members, function (i, data) {
                            var tempObj = {id: data.locale, name: data.displayName, localeName: data.locale};
                            localeList[i] = tempObj;
                            if(system_locale_name == tempObj.displayName){
                                system_locale = tempObj.id;
                            }
                        });
                        $(LOCALE).hpSearchCombo({results: localeList, maxResults: localeList.length});
                        // Set the current server locale to combo box.
                        $(LOCALE).hpSearchCombo('set', {id: system_locale, name: system_locale_name});
                        $(LOCALE_INPUT).attr('name', 'locale_input');
                        dispatcher.fire("fieldUpdated",true);
                    },
                    error: function (){
                }});
            }
            /**
             * @private
             *
             */
            function setDateTime(handlers){
                if(($(TIME_AND_PLACE_RADIO_GRP).attr('id') ==
                    $(TIME_SYNC_MANUAL).attr('id')) &&
                    $(CURRENT_DATE_TIME_TEXT).val()){
                  // if manual set Date Time
                    dateTimePresenter.setDateTime($(CURRENT_DATE_TIME_TEXT).val(),{
                    success: function() {
                        handlers.success.call(this);
                      },
                    error: function (errorInfo){
                      onSetConfigError(errorInfo);
                        handlers.error(errorInfo);
                   }});
                }else{
                  // If synchnoronus with NTP is selected ,set the NTP
                    if($(NTP_SERVER_TEXT+'1').val()){
                        var ntpServerGroup=[];
                        for(var index = 1;index <= MAX_NTP_SERVERS_CONFIGURABLE;index = index+1){
                            ntpServerGroup.push($(NTP_SERVER_TEXT+index).val());
                        }
                        dateTimePresenter.setNTPservers(ntpServerGroup,{
                            success: function() {
                              handlers.success.call(this);
                            },
                            error: function (errorInfo){
                              onSetConfigError(errorInfo);
                              handlers.error(errorInfo);
                         }});
                    }

                }
            }

            function setTimezone(handlers)
            {
               if($(TIMEZONE).text() != ""){
                     //set time zone then Date Time OR NTP on success of TIMEZONE
                      dateTimePresenter.setTimezone($(TIMEZONE).text(),{
                          success: function() {
                             setDateTime(handlers);
                          },
                          error: function (errorInfo){
                           // Handle TimeZone Errors
                            onSetConfigError(errorInfo);
                            handlers.error(errorInfo);
                       }});
                   }

            }
     function registerEvents() {
                dateTimePresenter.on("dateAndTimeChange", showDateTime);
                dateTimePresenter.on("ntpServersChange", showNTPservers);
                dateTimePresenter.on("timezoneChange", showTimezone);
                dateTimePresenter.on("localeChange", showLocale);

           }
            function removeEvents() {
                dateTimePresenter.off("dateAndTimeChange", showDateTime);
                dateTimePresenter.off("ntpServersChange", showNTPservers);
                dateTimePresenter.off("timezoneChange", showTimezone);
                dateTimePresenter.off("localeChange", showLocale);

            }
            function getNTPservers() {
                dateTimePresenter.getNTPservers();
            }
            function showHideDateTimeSettings(){
                $('input:radio[name='+TIME_AND_PLACE_CHOOSER+']').click(function() {
                    if($(TIME_AND_PLACE_RADIO_GRP).attr('id') === $(TIME_SYNC_MANUAL).attr('id')){
                        $(NTP_SERVER).hide();
                        $(CURRENT_DATE_TIME_LABEL_GROUP).hide();
                        $(CURRENT_DATE_TIME).show();
                        $(CURRENT_DATE_TIME).val('');
                        $(DATETIME_WARNING).show();
                        isManualSetting = true;
                    }else{
                        clickEventForSync = true;
                        $(CURRENT_DATE_TIME_LABEL_GROUP).show();
                        getNTPservers();
                        $(NTP_SERVER).show();
                        $(CURRENT_DATE_TIME).hide();
                        $(DATETIME_WARNING).hide();
                        isManualSetting = false;
                    }
                    registerClock(true);
                });
            }

            this.setTimeAndPlace = function(handlers,validator){
                if(!$(FORM).valid()) {
                    return;
                }

                if($(LOCALE).text() != ""){
                    //set locale , time zone then Date Time OR NTP on success of TIMEZONE
                    locale_val = $(LOCALE).val();
                    var locale = localeList[locale_val];
                    // To handle if user is enter the locale which is not presnt in the list.
                    if(typeof locale !== 'undefined'){
                        locale_str = locale.localeName ;
                      }else{
                           locale_str = locale_val;
                      }
                     dateTimePresenter.setLocale(locale_str,{
                         success: function() {
                            setTimezone(handlers);
                         },
                         error: function (errorInfo){
                          // Handle TimeZone Errors
                           onSetConfigError(errorInfo);
                           handlers.error(errorInfo);
                      }});
                  }
            };

           /**
             * @public Initialization method
             */
            this.init = function() {
                registerEvents();
                $(NTP_SERVER).hide();
                $(CURRENT_DATE_TIME_LABEL_GROUP).hide();
                getNTPservers();
                getDateTime();
                showHideDateTimeSettings();

                $(CURRENT_DATE_TIME_TEXT).datetimepicker({
                    timeFormat: 'HH:mm:ss',
                    dateFormat: 'yy-mm-dd'
                });

                dateTimePresenter.getTimezone();
                dateTimePresenter.getLocale();

                $.validator.addMethod(
                   'hpTimeandlanguageNtpAddress',
                   dateTimePresenter.validateNTPField,
                   localizer.getString('fs.settings.network.validator.ntpserver.ntp_fqdn_required')
                );

                $(CURRENT_DATE_TIME_TEXT).change(function(){
                    dateTimeUnixTS = Date.parse(new Date(dateTimePresenter.parseDateTime($(CURRENT_DATE_TIME_TEXT).val())));
                });

                resetFailures();
            };
            this.pause = function() {
                removeEvents();
                registerClock(false);
            };
            this.resume = function() {
                resetFailures();
                getNTPservers();
                dateTimePresenter.getTimezone();
                dateTimePresenter.getLocale();
                getDateTime();

            };
            /**
             * Set the validator for the view.
             */
            this.setValidator = function(v) {
                validator = v;
            };
            /**
             * Set the form state view for the view.
             */
            this.setFormStateViewInstance = function(f) {
              formstateview  = f;
            };
         }
        return TimeAndPlaceView;
    }());
});
