var PAPI_tasksched_types = Object.freeze({
  SCAN: 1,
  MONI: 2,
  CAPTURE: 3,
  DATALOGGER: 4,
  TSRECORD: 5,
});

var PAPI_tasksched_types_strings = Object.freeze({
  SCAN: 'SCANNING',
  MONI: 'MONITORING',
  CAPTURE: 'CAPTURE',
  DATALOGGER: 'DATALOGGER',
  TSRECORD: 'TSRECORD',
  AUDIORECORD: 'AUDIORECORD',
  ETIRECORD: 'ETIRECORD',
});

var PAPI_tasksched_reptypes = Object.freeze({
  BOOT: 1,
  HOURLY: 2,
  WEEKLY: 3,
  MONTHLY: 4,
  NONE: 5,
});

var PAPI_tasksched_reptypes_strings = Object.freeze({
  BOOT: 'BOOT',
  HOURLY: 'HOURLY',
  WEEKLY: 'WEEKLY',
  MONTHLY: 'MONTHLY',
  NONE: 'NONE',
});

var PAPI_tasksched_capturetypes = Object.freeze({
  SCREEN: 1,
  DATA: 2,
  BOTH: 3,
});

var PAPI_tasksched_capturetypes_strings = Object.freeze({
  SCREEN: 'SCREEN',
  DATA: 'DATA',
  BOTH: 'BOTH',
});

var PAPI_tasksched_captureforms = Object.freeze({
  SP1: 1,
  SP2: 2,
  SP3: 3,
  MEAS1: 4,
  MEAS2: 5,
  MEAS3: 6,
  TV1: 7,
  TV2: 8,
  TV3: 9,
  IPTV: 10,
  IPMEAS: 11,
  INTERPA: 12,
});

var PAPI_tasksched_captureforms_strings = Object.freeze({
  SP1: 'SP1',
  SP2: 'SP2',
  SP3: 'SP3',
  MEAS1: 'MEAS1',
  MEAS2: 'MEAS2',
  MEAS3: 'MEAS3',
  TV1: 'TV1',
  TV2: 'TV2',
  TV3: 'TV3',
  IPTV: 'IPTV',
  IPMEAS: 'IPMEAS',
  INTERPA: 'INTERPA',
});

var PAPI_tasksched_tsrecordbands = Object.freeze({
  TER: 1,
  SAT: 2,
});

var PAPI_tasksched_tsrecordbands_strings = Object.freeze({
  TER: 'BAND_TER',
  SAT: 'BAND_SAT',
});

var PAPI_tasksched_tsrecord;

function PAPI_tasksched_Handler(handler) {
  var get_command = function (id, param) {
    return new PAPI_newClientData(PAPI_data_type.CMD, 'TASKSCHED ' + id, param);
  };

  var get_question = function (id, param) {
    return new PAPI_newClientData(PAPI_data_type.CMD, '?TASKSCHED ' + id, param);
  };

  /*
   * obj|
   *    |startTimeTask
   *    |executionTimeTask
   *    |timeIntervalTask --> will disappear
   *    |exd
   *    |type
   *    |reptype
   *    |p1
   *    |p2
   *    |extraInfo(has a name for every type)
   *      |grpid; //SCAN
   *      |monid; //MONITORING
   *      |captureinfo; //CAPTURE
   *        |type
   *        |form
   *      |dataloggername;
   *      |tsrecordinfo;
   *        |band->nombre
   *        |channel -> num
   *        |channelPlan ->nombre
   *        |service ->num
   *        |plp ->num
   *        |recordname ->path
   */
  this.ScheduleTaskCmd = function (obj) {
    let ret = '';

    //Remove seconds and milliseconds from startTime and expireDate
    obj.startTimeTask.seconds(0).milliseconds(0);

    if (obj.expireDateTask != '0') {
      obj.expireDateTask.seconds(0).milliseconds(0);
    }

    if (obj.reptype == 'NONE') {
      obj.expireDateTask = '0';
      obj.executionTimeTask = '0';
    }

    switch (obj.type) {
      case PAPI_tasksched_types_strings.SCAN:
        ret = getScheduleScanTaskCmd.call(this, obj);
        break;
      case PAPI_tasksched_types_strings.MONI:
        ret = getScheduleMoniTaskCmd.call(this, obj);
        break;
      case PAPI_tasksched_types_strings.CAPTURE:
        ret = getScheduleCaptureTaskCmd.call(this, obj);
        break;
      case PAPI_tasksched_types_strings.DATALOGGER:
        ret = getScheduleDataloggerTaskCmd.call(this, obj);
        break;
      case PAPI_tasksched_types_strings.TSRECORD:
        ret = getScheduleTSRecordTaskCmd.call(this, obj);
        break;
      case PAPI_tasksched_types_strings.ETIRECORD:
        ret = getScheduleETIRecordTaskCmd.call(this, obj);
        break;
      case PAPI_tasksched_types_strings.AUDIORECORD:
        ret = getScheduleAudioRecordTaskCmd.call(this, obj);
        break;
    }

    handler.send(get_question(ret));
    //return ret;
  };

  getTimeConf = function (obj) {
    let startTime = Math.trunc(obj.startTimeTask / 1000); //Should expect start time to be sent in ms
    let expireDate = Math.trunc(obj.expireDateTask / 1000);
    let calcp1 = this.getP1(obj.p1, obj.reptype);
    let calcp2 = this.getP2(obj.p2, obj.reptype);
    return ' RT=' + obj.reptype + ' P1=' + calcp1 + ' P2=' + calcp2 + ' ET=' + obj.executionTimeTask + ' ST=' + startTime + ' EXD=' + expireDate;
  };

  getScheduleScanTaskCmd = function (obj) {
    let timeTxt = getTimeConf.call(this, obj);
    return 'NEW TYPE=SCAN GRP=' + obj.extraInfo.grpId + timeTxt;
  };

  getScheduleMoniTaskCmd = function (obj) {
    let timeTxt = getTimeConf.call(this, obj);
    return 'NEW TYPE=MONI MONID=' + obj.extraInfo.monId + timeTxt;
  };

  getScheduleCaptureTaskCmd = function (obj) {
    let timeTxt = getTimeConf.call(this, obj);
    return 'NEW TYPE=CAPTURE CT=' + obj.extraInfo.captureInfo.type + ' FORM=' + obj.extraInfo.captureInfo.form + timeTxt;
  };

  getScheduleDataloggerTaskCmd = function (obj) {
    let timeTxt = getTimeConf.call(this, obj);
    return 'NEW TYPE=DATALOGGER NAME=' + obj.extraInfo.dataloggerName + timeTxt;
  };

  getScheduleTSRecordTaskCmd = function (obj) {
    let timeTxt = getTimeConf.call(this, obj);
    return (
      'NEW TYPE=TSRECORD BAND=' +
      obj.extraInfo.recordInfo.band +
      ' CHANNEL={' +
      obj.extraInfo.recordInfo.channel +
      '} ' +
      hasService(obj.extraInfo.recordInfo.service) +
      hasPLP(obj.extraInfo.recordInfo.plp) +
      timeTxt
    );
  };

  getScheduleETIRecordTaskCmd = function (obj) {
    let timeTxt = getTimeConf.call(this, obj);
    return 'NEW TYPE=ETIRECORD CHANNEL={' + obj.extraInfo.recordInfo.channel + '} ' + hasService(obj.extraInfo.recordInfo.service) + timeTxt;
  };

  getScheduleAudioRecordTaskCmd = function (obj) {
    let timeTxt = getTimeConf.call(this, obj);
    return (
      'NEW TYPE=AUDIORECORD BAND=' +
      obj.extraInfo.recordInfo.band +
      ' CHANNEL={' +
      obj.extraInfo.recordInfo.channel +
      '} ' +
      hasService(obj.extraInfo.recordInfo.service) +
      hasPLP(obj.extraInfo.recordInfo.plp) +
      timeTxt
    );
  };

  this.getRemoveTaskCmd = function (obj) {
    handler.send(get_question('DELETE ID=', obj.idTask));
  };

  this.getEnableTaskCmd = function (obj) {
    handler.send(get_question('ENABLE ID=', obj.idTask));
  };

  this.getDisableTaskCmd = function (obj) {
    handler.send(get_question('DISABLE ID=', obj.idTask));
  };

  //TO DEVICE VALUES//
  this.getRPTstr = function (reptype) {
    let ret = '';
    switch (reptype) {
      case PAPI_tasksched_reptypes.BOOT:
        ret = PAPI_tasksched_reptypes_strings.BOOT;
        break;
      case PAPI_tasksched_reptypes.HOURLY:
        ret = PAPI_tasksched_reptypes_strings.HOURLY;
        break;
      case PAPI_tasksched_reptypes.WEEKLY:
        ret = PAPI_tasksched_reptypes_strings.WEEKLY;
        break;
      case PAPI_tasksched_reptypes.MONTHLY:
        ret = PAPI_tasksched_reptypes_strings.MONTHLY;
        break;
      case PAPI_tasksched_reptypes.NONE:
        ret = PAPI_tasksched_reptypes_strings.NONE;
        break;
    }
    return ret;
  };

  this.getCaptureType = function (type) {
    let ret = '';
    switch (type) {
      case PAPI_tasksched_capturetypes.SCREEN:
        ret = PAPI_tasksched_capturetypes_strings.SCREEN;
        break;
      case PAPI_tasksched_capturetypes.DATA:
        ret = PAPI_tasksched_capturetypes_strings.DATA;
        break;
      case PAPI_tasksched_capturetypes.BOTH:
        ret = PAPI_tasksched_capturetypes_strings.BOTH;
        break;
    }
    return ret;
  };

  this.getCaptureForm = function (form) {
    let ret = '';
    switch (form) {
      case PAPI_tasksched_captureforms.SP1:
        ret = PAPI_tasksched_captureforms.SP1;
        break;
      case PAPI_tasksched_captureforms.SP2:
        ret = PAPI_tasksched_captureforms.SP2;
        break;
      case PAPI_tasksched_captureforms.SP3:
        ret = PAPI_tasksched_captureforms.SP3;
        break;
      case PAPI_tasksched_captureforms.MEAS1:
        ret = PAPI_tasksched_captureforms.MEAS1;
        break;
      case PAPI_tasksched_captureforms.MEAS2:
        ret = PAPI_tasksched_captureforms.MEAS2;
        break;
      case PAPI_tasksched_captureforms.MEAS3:
        ret = PAPI_tasksched_captureforms.MEAS3;
        break;
      case PAPI_tasksched_captureforms.TV1:
        ret = PAPI_tasksched_captureforms.TV1;
        break;
      case PAPI_tasksched_captureforms.TV2:
        ret = PAPI_tasksched_captureforms.TV2;
        break;
      case PAPI_tasksched_captureforms.TV3:
        ret = PAPI_tasksched_captureforms.TV3;
        break;
      case PAPI_tasksched_captureforms.IPTV:
        ret = PAPI_tasksched_captureforms.IPTV;
        break;
      case PAPI_tasksched_captureforms.IPMEAS:
        ret = PAPI_tasksched_captureforms.IPMEAS;
        break;
      case PAPI_tasksched_captureforms.INTERPA:
        ret = PAPI_tasksched_captureforms.INTERPA;
        break;
    }
    return ret;
  };

  this.getTSRecordBand = function (tsrband) {
    let ret = '';
    switch (tsrband) {
      case PAPI_tasksched_tsrecordbands.TER:
        ret = PAPI_tasksched_tsrecordbands_strings.TER;
        break;
      case PAPI_tasksched_tsrecordbands.SAT:
        ret = PAPI_tasksched_tsrecordbands_strings.SAT;
        break;
    }
    return ret;
  };

  hasService = function (service) {
    let ret = '';
    if (service != '') {
      ret = ' SERVICE=' + service;
    }
    return ret;
  };

  hasPLP = function (plp) {
    let ret = '';
    if (plp != '') {
      ret = ' PLP=' + plp;
    }
    return ret;
  };

  //This function might return a negative number if the greater bit is set, the application should take it into account
  this.getP1 = function (p1, reptype) {
    let ret;
    switch (reptype) {
      case PAPI_tasksched_reptypes_strings.BOOT:
        ret = getBootP1(p1);
        break;
      case PAPI_tasksched_reptypes_strings.HOURLY:
        ret = getHourlyP1(p1);
        break;
      case PAPI_tasksched_reptypes_strings.WEEKLY:
        ret = getWeeklyP1(p1);
        break;
      case PAPI_tasksched_reptypes_strings.MONTHLY:
        ret = getMonthlyP1(p1);
        break;
      case PAPI_tasksched_reptypes_strings.NONE:
        ret = getNoneP1(p1);
        break;
      default: //default is incorrect behavior but avoids crash
        ret = -1;
        break;
    }
    return ret;
  };

  this.getP2 = function (p2, reptype) {
    let ret;
    switch (reptype) {
      case PAPI_tasksched_reptypes_strings.BOOT:
        ret = getBootP2(p2);
        break;
      case PAPI_tasksched_reptypes_strings.HOURLY:
        ret = getHourlyP2(p2);
        break;
      case PAPI_tasksched_reptypes_strings.WEEKLY:
        ret = getWeeklyP2(p2);
        break;
      case PAPI_tasksched_reptypes_strings.MONTHLY:
        ret = getMonthlyP2(p2);
        break;
      case PAPI_tasksched_reptypes_strings.NONE:
        ret = getNoneP2(p2);
        break;
      default:
        ret = -1;
        break;
    }
    return ret;
  };

  //expects number of hours. ex: 2
  getHourlyP1 = function (val) {
    return val;
  };
  //not used
  getHourlyP2 = function () {
    return 0;
  };

  //expects number of weeks. ex: 2
  getWeeklyP1 = function (val) {
    return val;
  };
  //expects array of days. ex: [1,3,7]
  getWeeklyP2 = function (arr) {
    let res = 0;
    arr.forEach(function (item, index, array) {
      res = res + (1 << (item - 1));
    });
    return res;
  };

  //expects array of days. ex[1,2,5,7,32]
  getMonthlyP1 = function (arr) {
    let res = 0;
    arr.forEach(function (item, index, array) {
      res = res + (1 << (item - 1));
    });
    return res;
  };
  //expects list of months. ex:
  getMonthlyP2 = function (arr) {
    let res = 0;
    arr.forEach(function (item, index, array) {
      res = res + (1 << (item - 1));
    });
    return res;
  };

  getBootP1 = function () {
    return 0;
  };
  getBootP2 = function () {
    return 0;
  };

  getNoneP1 = function () {
    return 0;
  };
  getNoneP2 = function () {
    return 0;
  };

  //TO WEB VALUES//
  this.getWebP1 = function (val, reptype) {
    let ret;
    switch (reptype) {
      case PAPI_tasksched_reptypes_strings.BOOT:
        ret = getBootWebP1(val);
        break;
      case PAPI_tasksched_reptypes_strigns.HOURLY:
        ret = getHourlyWebP1(val);
        break;
      case PAPI_tasksched_reptypes_strings.WEEKLY:
        ret = getWeeklyWebP1(val);
        break;
      case PAPI_tasksched_reptypes_strings.MONTHLY:
        ret = getMonthlyWebP1(val);
        break;
      case PAPI_tasksched_reptypes_strings.NONE:
        ret = getNoneWebP1(val);
        break;
      default:
        ret = -1;
        break;
    }
    return ret;
  };

  this.getWebP2 = function (val, reptype) {
    switch (reptype) {
      case PAPI_tasksched_reptypes_strings.BOOT:
        ret = getBootWebP2(val);
        break;
      case PAPI_tasksched_reptypes_strings.HOURLY:
        ret = getHourlyWebP2(val);
        break;
      case PAPI_tasksched_reptypes_strings.WEEKLY:
        ret = getWeeklyWebP2(val);
        break;
      case PAPI_tasksched_reptypes_strings.MONTHLY:
        ret = getMonthlyWebP2(val);
        break;
      case PAPI_tasksched_reptypes_strings.NONE:
        ret = getNoneWebP2(val);
        break;
      default:
        ret = -1;
        break;
    }
    return ret;
  };

  getHourlyWebP1 = function (val) {
    return val;
  };
  getHourlyWebP2 = function () {
    return 0;
  };

  getWeeklyWebP1 = function (val) {
    return val;
  };
  getWeeklyWebP2 = function (val) {
    let arr = [];
    for (let i = 0; i < 32; ++i) {
      if (val & (1 << i)) {
        arr.push((i + 1).toString());
      }
    }
    return arr;
  };

  getMonthlyWebP1 = function (val) {
    let arr = [];
    for (let i = 0; i < 32; ++i) {
      if (val & (1 << i)) {
        arr.push((i + 1).toString());
      }
    }
    return arr;
  };
  getMonthlyWebP2 = function (val) {
    let arr = [];
    for (let i = 0; i < 32; ++i) {
      if (val & (1 << i)) {
        arr.push((i + 1).toString());
      }
    }
    return arr;
  };

  getBootWebP1 = function () {
    return 0;
  };
  getBootWebP2 = function () {
    return 0;
  };

  getNoneWebP1 = function () {
    return 0;
  };
  getNoneWebP2 = function () {
    return 0;
  };
}
