/*
 * Stairs
 * Copyright 2017 (c) Mark van Renswoude
 *
 * https://git.x2software.net/pub/Stairs
*/
#include "./api.h"
#include <ArduinoJson.h>
#include <IPAddress.h>
#include <ESP8266WiFi.h>
#include "./shared.h"
#include "../assets/version.h"
#include "../debug.h"
#include "../global.h"
#include "../settings/connection.h"
#include "../settings/triggers/time.h"


void handleSet(AsyncWebServerRequest *request)
{
  _dln("API :: set");

  AsyncWebParameter* param;
  uint8_t value = 0;

  param = request->getParam("value");
  if (param != nullptr)
  {
    value = param->value().toInt();
  }
  else
  {
    param = request->getParam("percent");
    if (param != nullptr)
    {
      value = map(param->value().toInt(), 0, 100, 0, 255);
    }
    else
    {
      request->send(400);
      return;
    }
  }

  uint16_t time = 0;
  uint8_t from = 0;

  param = request->getParam("time");
  if (param != nullptr)
    time = param->value().toInt();

  param = request->getParam("from");
  if (param != nullptr)
  {
    if (param->value() == "top")
      from = 1;
    else if (param->value() == "bottom")
      from = 2;
  }


  if (from == 0 || time == 0)
    stairs->setAll(value, time, 0);
  else
    stairs->sweep(value, time, from == 1);

  request->send(200);
}


void handleGetStepValues(AsyncWebServerRequest *request)
{
  _dln("API :: get steps");

  DynamicJsonBuffer jsonBuffer(JSON_ARRAY_SIZE(17));

  bool target = !request->hasParam("current");

  JsonArray& root = jsonBuffer.createArray();
  for (uint8_t step = 0; step < stepsSettings->count(); step++)
    root.add(stairs->get(step, target));

  AsyncResponseStream *response = request->beginResponseStream("application/json");
  root.printTo(*response);

  request->send(response);
}


void handlePostStepValues(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total)
{
  _dln("API :: post steps");

  DynamicJsonBuffer jsonBuffer(2*JSON_ARRAY_SIZE(17) + JSON_OBJECT_SIZE(3) + 130);
  JsonObject& root = jsonBuffer.parseObject((char*)data);
  if (!root.success())
  {
    request->send(400);
    return;
  }

  uint16_t transitionTime = root["transitionTime"];
  JsonArray& values = root["values"];

  JsonArray& startTime = root["startTime"];
  size_t startTimeCount = startTime.size();

  size_t valueCount = values.size();
  if (valueCount > stepsSettings->count())
    valueCount = stepsSettings->count();


  for (uint8_t step = 0; step < valueCount; step++)
    stairs->set(step, values[step], transitionTime, step < startTimeCount ? startTime[step] : 0);

  request->send(200);
}


void handleGetTimeTriggers(AsyncWebServerRequest *request)
{
  _dln("API :: get time triggers");

  AsyncResponseStream *response = request->beginResponseStream("application/json");
  timeTriggerSettings->toJson(*response);
  request->send(response);
}


void handlePostTimeTriggers(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total)
{
  _dln("API :: post time triggers");

  bool changed;
  if (timeTriggerSettings->fromJson((char*)data, &changed))
  {
    timeTriggerSettings->write();

    if (changed)
      timeTriggerSettingsChanged = true;

    request->send(200);
  }
  else
    request->send(400);
}


void handleGetMotionTriggers(AsyncWebServerRequest *request)
{
  _dln("API :: get motion triggers");

  AsyncResponseStream *response = request->beginResponseStream("application/json");
  motionTriggerSettings->toJson(*response);
  request->send(response);
}


void handlePostMotionTriggers(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total)
{
  _dln("API :: post motion triggers");

  bool changed;
  if (motionTriggerSettings->fromJson((char*)data, &changed))
  {
    motionTriggerSettings->write();

    if (changed)
      motionTriggerSettingsChanged = true;

    request->send(200);
  }
  else
    request->send(400);
}


void registerAPIRoutes(AsyncWebServer* server)
{
  server->on("/api/set", HTTP_GET, handleSet);

  server->on("/api/steps/values", HTTP_GET, handleGetStepValues);
  server->on("/api/steps/values", HTTP_POST, devNullRequest, devNullFileUpload, handlePostStepValues);

  server->on("/api/triggers/time", HTTP_GET, handleGetTimeTriggers);
  server->on("/api/triggers/time", HTTP_POST, devNullRequest, devNullFileUpload, handlePostTimeTriggers);

  server->on("/api/triggers/motion", HTTP_GET, handleGetMotionTriggers);
  server->on("/api/triggers/motion", HTTP_POST, devNullRequest, devNullFileUpload, handlePostMotionTriggers);
}