import fs from 'fs'
import request from 'superagent'
import { ProxyAgent } from 'proxy-agent';

export default class AzureMaintEventService {

  constructor(config) {
    this.request = request;
    this.config = config;
    this.fs = fs;
    if (process.env.http_proxy) {
      this.proxy = process.env.http_proxy;
      this.proxyA = new ProxyAgent();
    }
  }

  async getEvents(loadFromCache, untilDate) {
    if (loadFromCache) {
      try {
        let result = this.fs.readFileSync(this.config.failSafeFilePath);
        result = JSON.parse(result);
        return result;
      } catch (error) {
        console.error('Error AzureMaintEventService getEvents, unable to read failSafe file: ' + error.message);
        return false;
      }
    } else {
      if (!untilDate) {
        untilDate = new Date();
      }
      let data = { "eventenddatetime": untilDate.toISOString() };
      let result = false;
      let response;
      if (this.proxy) {
        response = await this.request.post(this.config.url).agent(this.proxyA).send(data);
      } else {
        response = await this.request.post(this.config.url).send(data);
      }

      let liststr = "";
      if (response.status == 200 && response.text && response.text.length > 0) {
        liststr = response.text;
        liststr = liststr.replace(/(\r\n|\n|\r)/gm, "");
        liststr = liststr.replace('},]', '}]');
      } else {
        console.error("Maintenance events response not as expected");
        return false;
      }


      result = JSON.parse(liststr);
      // Write result to file a fallback solution in case retrieval fails in future runs
      this.fs.writeFileSync(this.config.failSafeFilePath,
        JSON.stringify(result, null, 2), function (err) {
          if (err) {
            console.error(err);
            return false;
          }
        }
      );
      return result;
    }
  }

  async isMaintenanceOngoing(loadFromCache, testStart, env) {
    // events eventenddatetime older then the passed time are not returned so we give the starttime of the test
    let events = await this.getEvents(loadFromCache, testStart);
    if (!events){
      return false;
    }
    env = env.toUpperCase();

    if (env == 'TST') { env = 'TEST' }
    else if (env == 'TRN') { env = 'TRAINING' }
    else if (env == 'PROD') { env = 'PRODUCTION' }
    else if (env == 'DEV') { env = 'DEVELOPMENT' }
    else if (env == 'INT') { env = 'INTEGRATION' }
    else if (env == 'DLT') { env = 'DATALOADTEST' }
    else if (env == 'ACC') { env = 'ACCEPTANCE' }
    else {
      console.error("AzureMaintEventService.isMaintenanceOngoing, UNKNOW ENVIRONMENT: " + env);
      return false;
    };

    let recordTypes = ["Standard Event", "Critical Event"] // Critical Period is not considered a maintenance event

    let impactedsystems = [];
    let impacteddomains = [];
    let allfeaturesimpacted = false;
    let result = false;

    events = events.filter(
      item => item.eventstartdatetime && (new Date(item.eventstartdatetime) <= testStart) &&
        item.eventenddatetime && (new Date(item.eventenddatetime) >= testStart) &&
        item.environments && item.environments.split(',').includes(env) &&
        recordTypes.includes(item.notificationtype)
    );

    if (events.length > 0) {
      events.forEach(event => {
        if (event.allfeaturesimpacted == "True") {
          allfeaturesimpacted = true;
        }
        impactedsystems.push(event.system);
        impacteddomains.push(event.impacteddomains);
      });
      // filter out duplicates
      impactedsystems = Array.from(new Set(impactedsystems));
      impacteddomains = Array.from(new Set(impacteddomains));

      result = {
        "impactedsystems": impactedsystems,
        "impacteddomains": impacteddomains,
        "allfeaturesimpacted": allfeaturesimpacted
      }
    }

    return result;
  }

  localTimeToUTC(dateString) {
    let date = new Date(dateString);
    return new Date(date.getTime() + (date.getTimezoneOffset() * 60000));
  }
}
