// CREATE A GIF FOCUSED GIF OR PNG OVER SELECTED COUNTRY
// anim variable can be true(for gif) or a number for timestep, for png
// call from interactive-forecast-viewer folder 
// date currently does not work, and defaults to current day, or most recent data
// country should have first letter capitalized, or coincide to coords.conf
// node create_country_loop true monarch 20220808 od550_dust Spain

const { Cluster } = require('puppeteer-cluster');
const util = require('util');
const path = require('path');
const url = 'http://127.0.0.1:9000/dashboard/'
const modelDict = {'od550_dust':'AOD',
	'sconc_dust':'Concentration',
	'dust_depd':'Dry deposition',
	'dust_depw':'Wet deposition',
	'dust_load':'Load',
	'dust_ext_sfc':'Extinction'};

//READ COORDINATES AND CENTER FROM CONF FILE
const relpath = path.relative('js/create_country_loop.js', 'interactive-forecast-viewer/conf/coords.json');
const coords = require(relpath);

function delay(time) {
 return new Promise(function(resolve) { 
   setTimeout(resolve, time)
 });
}

const RunCluster = async (anim, curmodel, seldate, variable, country) => {
  const cluster = await Cluster.launch({
    concurrency: Cluster.CONCURRENCY_CONTEXT,
    puppeteerOptions: {
        headless: true,
        args: [
            '--no-sandbox',
            '--disable-setuid-sandbox',
        ]
    },
    maxConcurrency: 4,
  });

  await cluster.task(async ({ page, data: args }) => {
      process.stdout.write("ARGS: " + args + "\n");
      var tstep = args[0];
      var curmodel = args[1];
      var seldate = args[2];
      var variable = args[3];
      var country = args[4];
      process.stdout.write("TSTEP: " + tstep + " -- MOD: " + curmodel + " -- DATE: " + seldate + " -- VAR: " + variable +' country: ' + country + "\n");
      await page.setViewport({ width: 1280, height: 768});
      await page.goto(url, {
          waitUntil: 'networkidle0',
      });
      await page.waitForSelector("#graph-collection");
      await page.waitForSelector(".graph-with-slider");
      // select variable
	  try {            
	  	const sel = await page.$('#variable-dropdown-forecast');
		await sel.click();
		await page.waitForSelector(".Select-menu-outer");
		const dropdown_variable = modelDict[variable];
		process.stdout.write("Selected dropdown variable: " + dropdown_variable + '\n');
		await page.evaluate((dropdown_variable) => {
				const options = [...document.querySelectorAll('.VirtualizedSelectOption')];
				selected_variable = options.find(element => element.textContent === dropdown_variable);
				selected_variable.click();
				}, dropdown_variable);
	} catch (err) {
            process.stdout.write("ERR0: " + err + "\n");
	}
      // select all models 
	  if (curmodel === "all") {
		  try {            
              process.stdout.write("SELECT ALL MODELS\n");
              for (const model of await page.$$('.custom-control-input')) {
                  const checked = await model.evaluate(elem => elem.checked);
                   process.stdout.write("CHECKED BEFORE: " + checked + "\n");
                   if (!checked) {
                       await model.click();
                   }
              }
        } catch (err) {
            process.stdout.write("ERR1: " + err + "\n");
        }
      }
      // select only one model 
      else {
        try {            
                  process.stdout.write("SELECT MODEL: " + curmodel + "\n");
              for (const model of await page.$$('.custom-control-input')) {
                  const checked = await model.evaluate(elem => elem.checked);
                process.stdout.write("CHECKED BEFORE: " + checked + "\n");
                  const value = await model.evaluate(elem => elem.value);
                process.stdout.write("VALUE: " + value + "\n");
                if (!checked && value === curmodel) {
                await model.click();
                }
                if (checked && value !== curmodel) {
                await model.click();
                await delay(500);
                }
              }
        } catch (err) {
            process.stdout.write("ERR1: " + err + "\n");
        }
      }
      // apply button
      try {
            for (const model of await page.$$('.custom-control-input')) {
                const checked = await model.evaluate(elem => elem.checked);
                process.stdout.write("CHECKED AFTER: " + checked + "\n");
            }
            process.stdout.write("CLICK APPLY BUTTON\n");
            const btn = await page.$('#models-apply');
            await btn.click();  // "button#models-apply");
            await delay(500);
      } catch (err) {
          process.stdout.write("ERR2: " + err + "\n");
      }
      // apply none country button
	  try {
		  var zoom = coords[country].zoom;
		  var lat = coords[country].lat;
		  var lon = coords[country].lon;
		  process.stdout.write("Zoom: " + zoom  + " Lat " + lat + " Lon " + lon +"\n");
		  
		  // Change hidden inputs and button to visible
		  let zoomInput = await page.$('#country-zoom');
		  await zoomInput.evaluate((el) => el.style.display = 'block');
		  let latInput = await page.$('#country-lat');
		  await latInput.evaluate((el) => el.style.display = 'block');
		  let lonInput = await page.$('#country-lon');
		  await lonInput.evaluate((el) => el.style.display = 'block');
		  let zoomButton = await page.$('#country-focus');
		  await zoomButton.evaluate((el) => el.style.display = 'block');

		  // Add data and click 
		  await page.type('#country-zoom', zoom);
		  await page.type('#country-lat', lat);
		  await page.type('#country-lon', lon);
		  process.stdout.write("CLICK HIDDEN COUNTRY BUTTON\n");
		  await page.click('#country-focus');

		  // Make elements invisible again
		  await zoomInput.evaluate((el) => el.style.display = 'none');
		  await latInput.evaluate((el) => el.style.display = 'none');
		  await lonInput.evaluate((el) => el.style.display = 'none');
		  await zoomButton.evaluate((el) => el.style.display = 'none');

	  } catch (err) {
		  process.stdout.write("ERR3: " + err + "\n");
	  }
	  var num = "00";
	  if (tstep === "false") {
		  process.stdout.write("CURRENT SELECTION: " + tstep + "\n");
		  num = "_curr";
	  } else {
		  process.stdout.write("CURRENT TSTEP: " + tstep + "\n");
		  const steps = await page.$$("span.rc-slider-dot");
		  await steps[tstep].click();
		  if (tstep<10) {
			  num = "0"+tstep;
		  } else {
			  num = tstep;
		  }
	  }
	  // wait for alert div to disappear to start grabbing elements 
      await page.waitForSelector("#alert-forecast", {hidden: true});
      await page.waitForSelector("#graph-collection");
      const graph = await page.$('#graph-collection');
      // remove timeslider 
      await page.waitForSelector(".layout-dropdown");
      process.stdout.write("REMOVING LAYOUT DROPDOWN" + "\n");
      await page.evaluate((sel) => {
          let toRemove = document.querySelector(sel);
          toRemove.parentNode.removeChild(toRemove);
      }, '.layout-dropdown');
      // remove zoom panel 
      process.stdout.write("REMOVING ZOOM PANEL(S)" + "\n");
      await page.waitForSelector(".leaflet-bar");
      await page.evaluate((sel) => {
          let toRemove = document.querySelectorAll(sel);
      for (let j=0; j<toRemove.length; j++) {
              toRemove[j].parentNode.removeChild(toRemove[j]);
      }
      }, '.leaflet-bar');

      const outputFile = './tmp/' + variable.toLowerCase() + '/' + seldate + '_' + curmodel + '_' + country + '_' + num + '.png';
      process.stdout.write("TAKE SCREENSHOT => " + outputFile + "\n");
      await graph.screenshot({ path: outputFile });

    });

    if (anim === "true") {
        for (let i=0; i<25; i++) {
            try {
                process.stdout.write("QUEUEING step:" + i + "\n");
                await cluster.queue([i, curmodel, seldate, variable, country]);
            } catch (err) {
                console.log(err);
                      process.stdout.write("ERROR:" + err + "\n");
            }
        }
    } else {
        process.stdout.write("QUEUEING current:" + anim + "\n");
        cluster.queue([anim, curmodel, seldate, variable, country]);
    }

    await cluster.idle();
    await cluster.close();
}

var anim = process.argv[2];      // default: false;
var curmodel = process.argv[3];  // default: "none";
var seldate = process.argv[4];   // default: "none";
var variable = process.argv[5];  // default: OD550_DUST
var country = process.argv[6];  // default: Spain

process.stdout.write("START -> ANIM: " + anim + " CURMODEL: " + curmodel + " DATE: " + seldate + " VAR: " +  variable + " country: " + country + "\n");
RunCluster(anim, curmodel, seldate, variable, country);

