var fs = require("fs");
const bent = require("bent");
const mysql = require("mysql");
const tools = require("../../functions");
const _ = require("underscore");

let con = undefined;
let config;

function requestWithPromise(n) {
  const listURL =
    "http://www.opentopia.com/hiddencam.php?showmode=standard&country=%2A&seewhat=highlyrated&p=";
  return new Promise(function (resolve, reject) {
    const request = bent(listURL + n, "GET", 200);
    request().then(
      function (body) {
        body.text().then(function (text) {
          resolve(text);
        });
      },
      function (err) {
        console.warn(
          "[" +
            getModuleMeta().title +
            "] Was unable to resolve request with error: " +
            err
        );
      }
    );
  });
}

function initialize(connection, configL, replaceOld = false) {
  con = connection;
  config = configL;
  if(!fs.existsSync("./apiHandler/opentopia/FLAG")){
    fs.writeFileSync("./apiHandler/opentopia/FLAG", "")
    replaceOld = true
  }
  if (replaceOld) { // Just do it once, calling that API ain't cheap
    var array = fs
      .readFileSync("./apiHandler/opentopia/db_table_config.sql")
      .toString()
      .split("\n");

    for (i in array) {
      con.query(array[i], function (err, result) {
        tools.handleMysqlErrors(err, getModuleMeta().title + "L32");
        console.log("Table created for " + getModuleMeta().title);
      });
    }

    let allProms = [];

    for (let n = 0; n < 26; n++) {
      allProms.push(requestWithPromise(n));
    }

    const mysqlQuery =
      "INSERT INTO opentopia (name, source_id, loc, protocol_id, link) VALUES (?, ?, POINT(?, ?), ?, ?)";

    Promise.all(allProms).then(function (res) {
      for (l in res) {
        const baseurl = "http://www.opentopia.com/webcam/";
        let allResults = [];
        // Process the pages
        let part = res[l].split("<body>")[1];
        part = part.split("/webcam/");
        part.shift();
        for (h in part) {
          part[h] = part[h].replace("\t", "");
          part[h] = part[h]
            .split('target="_self">')[0]
            .replace('"', "")
            .split(">")[0];
        }

        pages = part;
        camProms = [];
        for (let pI = 0; pI < pages.length; pI++) {
          camProms.push(
            new Promise(function (resolve, reject) {
              const url = baseurl + pages[pI] + "?viewmode=livevideo";
              _.throttle(function () {
                setTimeout(function () {
                  const request = bent(url, "GET", 200);
                  request().then(
                    function (body) {
                      body.text().then(function (text) {
                        let pre;
                        let result = {
                          name: "",
                          url: "",
                          location: { lat: 0, lng: 0 },
                        };
                        try {
                          const body = text;

                          let part = body.split("<body>")[1];
                          camPart = part.split('<div class="big">')[1];
                          camPart = camPart.split('<img src="')[1];
                          camPart = camPart.split('"')[0];
                          result.url = camPart;
                          part = part.split("Facility")[1];
                          part = part.split("Rating")[0];
                          part = part.split('<label class="right">')[1];
                          pre = part;

                          result.name = part.split("</label></div>")[0];
                          result.name = result.name
                            .replaceAll("\t", "")
                            .replaceAll("  ", "");
                          part = part.split('<label class="right geo">')[1];

                          part = part.split('<span class="latitude">')[1];
                          result.location.lat = parseFloat(
                            part.split("</span>")[0]
                          );
                          part = part.split('<span class="longitude">')[1];
                          result.location.lng = parseFloat(
                            part.split("</span>")[0]
                          );
                          resolve(result);
                        } catch (ex) {
                          if (pre == undefined) {
                            resolve([]);
                          } else {
                            let reqPart1;
                            let reqPart2;
                            try {
                              reqPart1 = pre
                                .split('locality">')[1]
                                .split("</label>")[0];
                            } catch (error) {
                              reqPart1 = pre
                                .split('region">')[1]
                                .split("</label>")[0];
                            }
                            reqPart2 = pre
                              .split('country-name">')[1]
                              .split("</label>")[0];
                            const geoCoderReq = bent(
                              "https://open.mapquestapi.com/geocoding/v1/address?key=" +
                                config.mapquest +
                                "&location=" +
                                reqPart1 +
                                "," +
                                reqPart2,
                              "GET",
                              "json",
                              200
                            );
                            geoCoderReq().then(function (body) {
                              result.location.lat =
                                body.results[0].locations[0].latLng.lat;
                              result.location.lng =
                                body.results[0].locations[0].latLng.lng;
                              resolve(result);
                            });
                            console.log(reqPart1 + "," + reqPart2);
                          }
                        }
                      });
                    },
                    function (err) {
                      console.warn(
                        "[" +
                          getModuleMeta().title +
                          "] Was unable to resolve request with error: " +
                          err
                      );
                    }
                  );
                }, Math.floor(Math.random() * 500));
              }, 200)();
            })
          );
          let globalI = 0;
          Promise.all(camProms).then(function (result) {
            // console.log(result);
            for (elm in result) {
              const row = result[elm];
              globalI++;
              try {
                con.query(
                  mysqlQuery,
                  [
                    row.name,
                    getModuleMeta().exactName,
                    row.location.lat,
                    row.location.lng,
                    0,
                    row.url,
                  ],
                  function (err, result) {
                    if (err) {
                      if (err.code == "ER_DUP_ENTRY") {
                        //console.warn("[Opentopia] Skipped duplicate webcam");
                      } else {
                        tools.handleMysqlErrors(
                          err,
                          getModuleMeta().title + "L128"
                        );
                      }
                    }
                  }
                );
              } catch (error) {
                /*console.warn(
                "[Opentopia] Experienced an issue adding element to DB, error was: " +
                  error
              );*/
              }
            }
          });
        }
      }
    });
  }
}

function queryData(boundNorthEastLatLng, boundSouthWestLatLng, minimal) {
  return new Promise(function (resolve, reject) {
    // The Promise constructor should catch any errors thrown on
    // this tick. Alternately, try/catch and reject(err) on catch.
    var connection = con;

    let elementsToQuery = "*";
    if (minimal) {
      elementsToQuery = "id,loc,source_id";
    }

    const sqlQuery = " \
    SELECT " + elementsToQuery + " \
FROM opentopia \
WHERE MBRContains( \
  GeomFromText( 'LINESTRING(? ?,? ?)' ), \
  loc)";


  con.query(sqlQuery, [boundNorthEastLatLng.lat, boundNorthEastLatLng.lng, boundSouthWestLatLng.lat, boundSouthWestLatLng.lng], function (err, rows, fields) {
        // Call reject on error states,
        // call resolve with results
        if (err) {
          tools.handleMysqlErrors(err, getModuleMeta().title + "-L187");
          return reject(err);
        }
        let results = [];
        for (let e = 0; e < rows.length; e++) {
          const currentRow = rows[e];
          element = {
            type: "webcam-iframe",
            source: "Opentopia",
            titel: currentRow.name,
            description: "An example webcam with a url",
            url: currentRow.link,
            uid: "opentopia_" + currentRow.id,
            location: currentRow.loc,
            icon: "cctvIcon",
          };

          if (minimal) {
            const stripableElements = ["title", "description", "url", "type"];
            for (h in stripableElements) {
              delete element[stripableElements[h]];
            }
          }

          results.push(element);
        }
        resolve(results);
      }
    );
  });
}

function queryItem(uid) {
  const uidParts = uid.split("_");

  const sqlQuery = "SELECT * FROM " + getModuleMeta().exactName + " WHERE id=?";
  return new Promise(function (resolve, reject) {
    con.query(sqlQuery, [parseInt(uidParts[1])], function (err, rows, fields) {
      if (err) {
        tools.handleMysqlErrors(err, getModuleMeta().title + "L230");
        return reject(err);
      }
      const results = [];
      for (let e = 0; e < rows.length; e++) {
        const currentRow = rows[e];
        const element = {
          type: "webcam-iframe",
          source: "Opentopia",
          titel: currentRow.name,
          description: "An example webcam with a url",
          url: currentRow.link,
          uid: "opentopia_" + currentRow.id,
          location: currentRow.loc,
          icon: "cctvIcon",
        };
        results.push(element);
      }
      resolve(results);
    });
  });
}

function getModuleMeta() {
  return {
    title: "Opentopia",
    exactName: "opentopia",
    country: ["*"],
    tags: ["webcam"],
    limited: false,
  };
}

module.exports = { initialize, queryData, getModuleMeta, queryItem };
