// Global API configuration
var Api = new Restivus({
  version: 'v1.0',
  useDefaultAuth: true,
  prettyJson: true
});

Api.addRoute('sensorData', {
  authRequired: false
}, {
  post: function() {
    reactToSensorData(this.bodyParams);
    var sensorObject = {
      temperatureValue: parseFloat(this.bodyParams.temperatureValue),
      humidityValue: parseFloat(this.bodyParams.humidityValue),
      temperatures: this.bodyParams.temperatures,
      tankLevel0: this.bodyParams.tankLevel0,
      tankLevel1: this.bodyParams.tankLevel1,
      tankLevel2: this.bodyParams.tankLevel2,
      tankLevel3: this.bodyParams.tankLevel3,
      tankLevel4: this.bodyParams.tankLevel4,
      tankFull: this.bodyParams.tankFull,
      startPumpingAt: this.bodyParams.startPumpingAt,
      stopPumpingAt: this.bodyParams.stopPumpingAt,
      owner: this.bodyParams.owner,
      controllerId: this.bodyParams.controllerId,
      lastBoxContact: new Date(),
      created_at: new Date()
    };
    SensorData.insert(sensorObject);
    reactToAlarmData(this.bodyParams.controllerId);
    return [];
  }
});

Api.addRoute('alarm/:id/phonePing', {
  authRequired: false
}, {
  post: function() {
    ControllerState.update({
      controller_id: this.urlParams.id
    }, {
      '$set': {
        'lastPhoneContact': new Date(),
      }
    });
    var state = stateOrDefault(this.urlParams.id).state;

    if(state.alarmTriggered) {
      return {
        'alarmTriggered': state.alarmTriggered,
        'tooHot': state.alarmReasons.tooHot,
        'tooCold': state.alarmReasons.tooCold,
        'phoneSilent': state.alarmReasons.phoneSilent,
        'boxSilent': state.alarmReasons.boxSilent
      };
    } else {
      return {};
    }

  }
});


reactToSensorData = function(nextSensorReading) {
  console.log("reacting to sensor");
  var controllerId = nextSensorReading.controllerId;
  var stateObject = stateOrDefault(controllerId);
  var state = stateObject.state;
  var config = stateObject.config;

  var startPumpingLevelReached;
  if (nextSensorReading.startPumpingAt == 'TANKLEVEL0') startPumpingLevelReached = (parseInt(nextSensorReading.tankLevel0) === 0)
  else if (nextSensorReading.startPumpingAt == 'TANKLEVEL1') startPumpingLevelReached = (parseInt(nextSensorReading.tankLevel1) === 0)
  else if (nextSensorReading.startPumpingAt == 'TANKLEVEL2') startPumpingLevelReached = (parseInt(nextSensorReading.tankLevel2) === 0)
  else if (nextSensorReading.startPumpingAt == 'TANKLEVEL3') startPumpingLevelReached = (parseInt(nextSensorReading.tankLevel3) === 0)
  else if (nextSensorReading.startPumpingAt == 'TANKLEVEL4') startPumpingLevelReached = (parseInt(nextSensorReading.tankLevel4) === 0)
  else startPumpingLevelReached = true;

  var shouldStartAutomaticPumping = (!state.in_valve || state.in_valve === 'closed') && ((parseInt(nextSensorReading.tankFull) === 0) && startPumpingLevelReached && (state.out_valve === 'closed' || state.out_valve === 'closing'));

  console.log("State: ", state);

  var shouldStartPumping = shouldStartAutomaticPumping && config && !config.manualInflow;

  console.log("shouldStartAutomaticPumping: ", shouldStartAutomaticPumping);

  console.log("shouldStartPumping: ", shouldStartPumping);

  if (shouldStartPumping) {
    ControllerState.update({
      controller_id: controllerId
    }, {
      '$set': {
        'state.in_valve': 'opening',
        'time': new Date(),
        'set_by': 'server'
      }
    });
  }

  var stopPumpingLevelReached;
  if (nextSensorReading.stopPumpingAt == 'TANKLEVEL0') stopPumpingLevelReached = (parseInt(nextSensorReading.tankLevel0) === 1)
  else if (nextSensorReading.stopPumpingAt == 'TANKLEVEL1') stopPumpingLevelReached = (parseInt(nextSensorReading.tankLevel1) === 1)
  else if (nextSensorReading.stopPumpingAt == 'TANKLEVEL2') stopPumpingLevelReached = (parseInt(nextSensorReading.tankLevel2) === 1)
  else if (nextSensorReading.stopPumpingAt == 'TANKLEVEL3') stopPumpingLevelReached = (parseInt(nextSensorReading.tankLevel3) === 1)
  else if (nextSensorReading.stopPumpingAt == 'TANKLEVEL4') stopPumpingLevelReached = (parseInt(nextSensorReading.tankLevel4) === 1)
  else stopPumpingLevelReached = false;

  var shouldStopAutomaticPumping = (state.in_valve === 'open' || state.in_valve === 'opening') && (parseInt(nextSensorReading.tankFull) === 1 || stopPumpingLevelReached || state.out_valve === 'open' || state.out_valve === 'opening');

  var shouldStopPumping = shouldStopAutomaticPumping && config && !config.manualInflow;

  console.log("shouldStopPumping: ", shouldStopPumping);


  if (shouldStopPumping) {
    ControllerState.update({
      controller_id: controllerId
    }, {
      '$set': {
        'state.in_valve': 'closing',
        'time': new Date(),
        'set_by': 'server'
      }
    });
  }
}

Api.addRoute('state/:id', {
  authRequired: false
}, {
  post: function() {
    console.log("setting state", this.bodyParams);
    return ControllerState.update({
      controller_id: this.urlParams.id
    }, {
      '$set': {
        'state.out_valve': this.bodyParams.out_valve,
        'state.in_valve': this.bodyParams.in_valve,
        'state.picture_requested': this.bodyParams.picture_requested,
        'time': new Date(),
        'set_by': 'client'
      }
    });
  },
  get: function() {
    return stateOrDefault(this.urlParams.id).state;
  }
});

Api.addRoute('picture/:id', {
  authRequired: false
}, {
  post: function() {
    console.log("setting picture", this.bodyParams);
    return Picture.upsert({
      controller_id: this.urlParams.id
    }, {
      '$set': {
        'picture_base64': this.bodyParams.picture_base64,
        'time': new Date()
      }
    });
  }
});

function base64_to_buffer(base64string) {
  var buf;
  if (typeof Buffer.from === "function") {
    buf = Buffer.from(base64string, 'base64');
  } else {
    buf = new Buffer(base64string, 'base64');
  }
  return buf;
}

function stateOrDefault(id) {
  var stateEntry = ControllerState.findOne({
    controller_id: id
  });

  if (stateEntry === undefined) {
    stateEntry = ControllerState.insert({
      controller_id: id,
      state: {
        out_valve: 'closed',
        in_valve: 'closed',
        alarmTriggered: false,
        alarmReasons: {
          tooHot: false,
          tooCold: false,
          boxSilent: false,
          phoneSilent: false
        }
      },
      time: new Date(),
      config: {
        draining_period_amount: 40,
        draining_period_unit: 'minutes',
        manualInflow: true
      },
      features: {
        start: true,
        weather: true,
        surveillance: true,
        log: true,
        alarm: true
      },
      set_by: 'server'
    });
  };
  var stateEntry = ControllerState.findOne({
    controller_id: id,
  });
  return stateEntry;
}
