import {
  addQueryParams, errorHandler, fetchRespHandler, getAuthHeaderOptions
} from "../utils/http";

const API_ENDPOINT = process.env.REACT_APP_OTA_SERVICE_URL;

const vehiclesAPI = {
  addVehicle: async (vehicle, token) =>
    fetch(`${API_ENDPOINT}/vehicle`, {
      method: "POST",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
      body: JSON.stringify(vehicle),
    })
      .then(fetchRespHandler)
      .catch(errorHandler),

  addTags: async (vins, tags, token) =>
    fetch(`${API_ENDPOINT}/tags`, {
      method: "POST",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token),
      ),
      body: JSON.stringify({ vins, tags }),
    })
      .then(fetchRespHandler)
      .catch(errorHandler),

  getConnections: async (vins, token) => {
    const u = `${API_ENDPOINT}/carsconnected`;
    return fetch(u, {
      method: "POST",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
      body: JSON.stringify(vins),
    })
      .then(fetchRespHandler)
      .catch(errorHandler);
  },

  getECUs: async (search, token) => {
    const u = addQueryParams(`${API_ENDPOINT}/vehicleecus`, search);
    return fetch(u, {
      method: "GET",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
    })
      .then(fetchRespHandler)
      .catch(errorHandler);
  },

  getModels: async (token) =>
    fetch(`${API_ENDPOINT}/vehiclemodels`, {
      method: "GET",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
    })
      .then(fetchRespHandler)
      .catch(errorHandler),

  getLocations: async (token) =>
    fetch(`${API_ENDPOINT}/carslocations`, {
      method: "GET",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
    })
      .then(fetchRespHandler)
      .catch(errorHandler),

  getLocationsVehiclePaths: async (token, param, vins) =>
    fetch(`${API_ENDPOINT}/vehicle_paths?${param}`, {
      method: "POST",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
      body: JSON.stringify({ vins: vins }),
    })
      .then(fetchRespHandler)
      .catch(errorHandler),

  getState: async (token, vin) =>
    fetch(`${API_ENDPOINT}/carstate?vin=${vin}`, {
      method: "GET",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
    })
      .then(fetchRespHandler)
      .catch(errorHandler),

  getVehicle: async (vin, token) =>
    fetch(`${API_ENDPOINT}/vehicle/${vin}`, {
      method: "GET",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
    })
      .then(fetchRespHandler)
      .catch(errorHandler),

  getVehicles: async (search, token) => {
    const u = addQueryParams(`${API_ENDPOINT}/vehicles`, search);
    return fetch(u, {
      method: "GET",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
    })
      .then(fetchRespHandler)
      .catch(errorHandler);
  },

  getFleets: async (vin, search, token) => {
    const u = addQueryParams(`${API_ENDPOINT}/vehicle/${vin}/fleets`, search)
    return fetch(u, {
      method: "GET",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
    })
      .then(fetchRespHandler)
      .catch(errorHandler);
  },

  getYears: async (token) =>
    fetch(`${API_ENDPOINT}/vehicleyears`, {
      method: "GET",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
    })
      .then(fetchRespHandler)
      .catch(errorHandler),

  sendCommand: async (vins, command, token) =>
    fetch(`${API_ENDPOINT}/vehiclecommand`, {
      method: "POST",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
      body: JSON.stringify({
        vins,
        ...command,
      }),
    })
      .then(fetchRespHandler)
      .catch(errorHandler),

  sendDiagnosticCommand: async (vins, command, token) =>
    fetch(`${API_ENDPOINT}/vehiclediagnosticcommand`, {
      method: "POST",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
      body: JSON.stringify({
        vins,
        ...command,
      }),
    })
      .then(fetchRespHandler)
      .catch(errorHandler),

  updateVehicle: async (vin, vehicle, token) =>
    fetch(`${API_ENDPOINT}/vehicle/${vin}`, {
      method: "PUT",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
      body: JSON.stringify(vehicle),
    })
      .then(fetchRespHandler)
      .catch(errorHandler),

  updateConfig: async (vin, forced, token) =>
    fetch(`${API_ENDPOINT}/car_config/${vin}?forced=${forced}`, {
      method: "POST",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      )
    })
      .then(fetchRespHandler)
      .catch(errorHandler),

  /**
   * 
   * @param {String} vin The VIN of the car
   * @param {Object} filter 
   * @param {Integer} filter.after_utc Point in time to begin signal response
   * @param {Integer} filter.limit Max number of CAN Signals to return
   * @param {String} token 
   * @returns {Array}
   */
  getCANSignals: async (vin, filter = {}, token) => {
    const url = addQueryParams(`${API_ENDPOINT}/cansignals/${vin}`, filter);
    return fetch(url, {
      method: "GET",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
    })
      .then(fetchRespHandler)
      .catch(errorHandler);
  },

  getTRexLogs: async (vin, search, date, offset, count, direction, token, controller) =>
    fetch(`${API_ENDPOINT}/vehicle/${vin}/trex-logs?date=${date}&offset=${offset}&count=${count}&direction=${direction}&search=${search}`, {
      method: "GET",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
      signal: controller.signal
    })
      .then(fetchRespHandler)
      .catch(errorHandler),

  getVersionLog: async ({ vin, ...search }, token) => {
    const u = addQueryParams(`${API_ENDPOINT}/vehicle/${vin}/version/logs`, search);
    return fetch(u, {
      method: "GET",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
    })
      .then(fetchRespHandler)
      .catch(errorHandler)
  },

  getLogFileLink: async ({ vin, year, month, day }, token) => {
    const u = `${API_ENDPOINT}/vehicle/${vin}/trex-logs-link?year=${year}&month=${month}&day=${day}`
    return fetch(u, {
      method: "GET",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
    }).then(fetchRespHandler)
      .catch(errorHandler)
  },

  getAllFlashpacks: async (model, trim, year, options, token) => {
    return fetch(addQueryParams(`${API_ENDPOINT}/flashpack_versions/${model}/${trim}/${year}`, options), {
      method: "GET",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
    }).then(fetchRespHandler)
      .catch(errorHandler)
  },

  getFlashpackECUMappings: async (model, trim, year, flashpack, options, token) => {
    return fetch(addQueryParams(`${API_ENDPOINT}/flashpack_version_ecu_mappings/${model}/${trim}/${year}/${flashpack}`, options), {
      method: "GET",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
    }).then(fetchRespHandler)
      .catch(errorHandler)
  },

  addFlashpackVersion: async (data, token) => {
    return fetch(`${API_ENDPOINT}/flashpack_version`, {
      method: "POST",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token),
      ),
      body: JSON.stringify(data),
    }).then(fetchRespHandler)
      .catch(errorHandler)
  },

  addFlashpackVersionECUMapping: async (model, trim, year, flashpack, data, token) => {
    return fetch(`${API_ENDPOINT}/flashpack_version_ecu_mapping/${model}/${trim}/${year}/${flashpack}`, {
      method: "POST",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token),
      ),
      body: JSON.stringify(data),
    }).then(fetchRespHandler)
      .catch(errorHandler)
  },

  deleteFlashpackVersion: async (data, token) => {
    return fetch(`${API_ENDPOINT}/flashpack_version`, {
      method: "DELETE",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
      body: JSON.stringify(data),
    }).then(fetchRespHandler)
      .catch(errorHandler)
  },

  deleteFlashpackVersionECUMapping: async (model, trim, year, flashpack, ecuName, ecuVersion, token) => {
    return fetch(`${API_ENDPOINT}/flashpack_version_ecu_mapping/${model}/${trim}/${year}/${flashpack}/${ecuName}/${ecuVersion}`, {
      method: "DELETE",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
    }).then(fetchRespHandler)
      .catch(errorHandler)
  },

  getCarFlashpackVersionInfo: async (vin, token) => {
    return fetch(`${API_ENDPOINT}/flashpack_version_info/${vin}`, {
      method: "GET",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
    }).then(fetchRespHandler)
      .catch(errorHandler)
  },

  flashpackVersionBulkUpdate: async (vins, token) => {
    return fetch(`${API_ENDPOINT}/flashpack_version_bulk_update`, {
      method: "PUT",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token),
      ),
      body: JSON.stringify({ vins }),
    }).then(fetchRespHandler)
      .catch(errorHandler)
  },

  getOSVersions: async (token) => {
    return fetch(`${API_ENDPOINT}/manifests_active_os_versions`, {
      method: "GET",
      headers: Object.assign(
        { "Content-Type": "application/json" },
        getAuthHeaderOptions(token)
      ),
    }).then(fetchRespHandler)
      .catch(errorHandler)
  },
};

export default vehiclesAPI;
