/**
 * NOTE: install "dark mode" on browser because tesseract need contract to detect text
 * NOTE: zoom 120% on browser because below
 */

const robotjs = require('robotjs')
const tesseract = require('tesseract.js')
const jsdom = require('jsdom')
const Jimp = require('jimp')
const CONFIG = {
  SCALE_IMAGE: 1.5,
  SCROLL_COUNT: 8,
}

module.exports = async function(keywordSearch, keywordToClick, scale = CONFIG.SCALE_IMAGE, fileScreenshot = 'screenshot.jpg', waitSearch = 2000) {
  if(!scale) {
    scale = CONFIG.SCALE_IMAGE
  }

  if(!fileScreenshot) {
    fileScreenshot = 'screenshot.jpg'
  }

  if(!waitSearch) {
    waitSearch = 2000
  }

  const $_randomInteger = (min, max) => {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  }

  async function handleToClick() {
    let _horc = '';
    let _text = '';
    let _coorStr = '';


    const _captureImage = async () => {
      const capture = robotjs.screen.capture()
      return new Promise(res => {
        new Jimp(
          {data: capture.image, width: capture.width, height: capture.height},
          (err, image) => {
            image.greyscale((err, image) => {
              image.scale(scale, (err, image) => {
                image.writeAsync(fileScreenshot).then(() => {
                  res(true)
                })
              })
            });
          });
      })
    }

    const _convertImageToDomString = async () => {
      await tesseract
        .recognize(fileScreenshot)
        .then(async ({data: {hocr, text}}) => {
          _horc = hocr
          _text = text
        })
    }

    const _detectHTML = async () => {
      console.log({keywordToClick, _text})
      return new Promise(async (resToFinished, rejToAgain) => {
        if(_text.includes(keywordToClick)) {
          const dom = new jsdom.JSDOM(_horc)
          const spanEls = dom.window.document.querySelectorAll('span')
          for await(let span of spanEls) {
            const textContent = span.textContent.split(' ').join('')
            if(textContent.includes(keywordToClick)) {
              _coorStr = span.title
              return resToFinished(true)
            }
          }
        }

        // scroll to 8 times
        for (let i = 1; i < CONFIG.SCROLL_COUNT; i++) {
          robotjs.keyTap('down')
        }
        rejToAgain(false)
      })
    }

    async function _handleClick() {
      const [type, left, top, right, bottom] = _coorStr.split(' ')
      const x = parseInt((parseInt(left) + $_randomInteger(20, 40)) / scale)
      const y = parseInt((parseInt(top) - $_randomInteger(0, parseInt(top) - parseInt(bottom))) / scale)
      robotjs.moveMouse(x, y)
      robotjs.mouseClick('left')
      console.log('moveMouse:', {x, y}, {
        left, bottom, right, top
      })
    }

    return new Promise(async (res, rej) => {
      await _captureImage();
      await _convertImageToDomString();
      await _detectHTML().then(_handleClick).catch(rej);
    })
  }

  await (async function search() {
    robotjs.keyTap('home', ['alt']);
    robotjs.typeString(keywordSearch);
    robotjs.keyTap('enter')
    return new Promise(res => setTimeout(res, waitSearch))
  }())

  await (async function recusiveScroll(countScroll = 1, limitStopScroll = 20) {
    if(countScroll > limitStopScroll) {
      return;
    }

    await handleToClick(keywordToClick, scale)
      .catch(async () => {
        await recusiveScroll(++countScroll, limitStopScroll)
      })
  }())
}
