/* eslint-disable no-case-declarations */

import _ from 'lodash';
import { errors } from 'appium-base-driver';
import BasePlugin from '@appium/base-plugin';
import { compareImages } from './compare';
import ImageElementFinder, { W3C_ELEMENT_KEY, MJSONWP_ELEMENT_KEY } from './finder';
import { ImageElement, IMAGE_ELEMENT_PREFIX } from './image-element';

const IMG_EL_BODY_RE = new RegExp(
  `"(${W3C_ELEMENT_KEY}|${MJSONWP_ELEMENT_KEY})":\s*` + // eslint-disable-line no-useless-escape
  `"${IMAGE_ELEMENT_PREFIX}[^"]+"`
);

const IMG_EL_URL_RE = new RegExp(
  `/(element|screenshot)` +
  `/${IMAGE_ELEMENT_PREFIX}[^/]+`
);

const IMAGE_STRATEGY = '-image';

function getImgElFromArgs (args) {
  for (let arg of args) {
    if (_.isString(arg) && arg.startsWith(IMAGE_ELEMENT_PREFIX)) {
      return arg;
    }
  }
}

export default class ImageElementPlugin extends BasePlugin {

  constructor (pluginName) {
    super(pluginName);
    this.finder = new ImageElementFinder();
  }

  // this plugin supports a non-standard 'compare images' command
  static newMethodMap = {
    '/session/:sessionId/appium/compare_images': {
      POST: {
        command: 'compareImages',
        payloadParams: {
          required: ['mode', 'firstImage', 'secondImage'],
          optional: ['options']
        },
        neverProxy: true,
      }
    },
  };

  shouldAvoidProxy (method, route, body) {
    // if it looks like we have an image element in the url (as a route
    // parameter), never proxy. Just look for our image element prefix in allowed
    // positions (either after an 'element' or 'screenshot' path segment), and
    // ensure the prefix is followed by something
    if (IMG_EL_URL_RE.test(route)) {
      return true;
    }


    // also if it looks like we have an image element in the request body (as
    // a JSON parameter), never proxy. Basically check against a regexp of the
    // json string of the body, where we know what the form of an image element
    // must be
    if (body) {
      const stringBody = JSON.stringify(body);
      if (stringBody && IMG_EL_BODY_RE.test(stringBody)) {
        return true;
      }
    }

    return false;
  }

  async compareImages (next, driver, ...args) {
    return await compareImages(...args);
  }

  async findElement (next, driver, ...args) {
    return await this._find(false, next, driver, ...args);
  }

  async findElements (next, driver, ...args) {
    return await this._find(true, next, driver, ...args);
  }

  async _find (multiple, next, driver, ...args) {
    const [strategy, selector] = args;

    // if we're not actually finding by image, just do the normal thing
    if (strategy !== IMAGE_STRATEGY) {
      return await next();
    }

    this.finder.setDriver(driver);
    return await this.finder.findByImage(selector, {multiple});
  }

  async handle (next, driver, cmdName, ...args) {
    // if we have a command that involves an image element id, attempt to find the image element
    // and execute the command on it
    const imgElId = getImgElFromArgs(args);
    if (imgElId) {
      if (!this.finder.imgElCache.has(imgElId)) {
        throw new errors.NoSuchElementError();
      }
      const imgEl = this.finder.imgElCache.get(imgElId);
      return await ImageElement.execute(driver, imgEl, cmdName, ...args);
    }

    // otherwise just do the normal thing
    return await next();
  }
}

export { ImageElementPlugin, getImgElFromArgs, IMAGE_STRATEGY };

@@ -223,50 +223,8 @@
 nder
-, %7B W3C_ELEMENT_KEY, MJSONWP_ELEMENT_KEY %7D
  fro
@@ -233,24 +233,24 @@
 './finder';%0A
+
 import %7B Ima
@@ -312,279 +312,8 @@
 ';%0A%0A
-const IMG_EL_BODY_RE = new RegExp(%0A  %60%22($%7BW3C_ELEMENT_KEY%7D%7C$%7BMJSONWP_ELEMENT_KEY%7D)%22:%5Cs*%60 + // eslint-disable-line no-useless-escape%0A  %60%22$%7BIMAGE_ELEMENT_PREFIX%7D%5B%5E%22%5D+%22%60%0A);%0A%0Aconst IMG_EL_URL_RE = new RegExp(%0A  %60/(element%7Cscreenshot)%60 +%0A  %60/$%7BIMAGE_ELEMENT_PREFIX%7D%5B%5E/%5D+%60%0A);%0A%0A
 cons
@@ -1027,837 +1027,14 @@
  %7D,%0A
+
   %7D;%0A%0A
-  shouldAvoidProxy (method, route, body) %7B%0A    // if it looks like we have an image element in the url (as a route%0A    // parameter), never proxy. Just look for our image element prefix in allowed%0A    // positions (either after an 'element' or 'screenshot' path segment), and%0A    // ensure the prefix is followed by something%0A    if (IMG_EL_URL_RE.test(route)) %7B%0A      return true;%0A    %7D%0A%0A%0A    // also if it looks like we have an image element in the request body (as%0A    // a JSON parameter), never proxy. Basically check against a regexp of the%0A    // json string of the body, where we know what the form of an image element%0A    // must be%0A    if (body) %7B%0A      const stringBody = JSON.stringify(body);%0A      if (stringBody && IMG_EL_BODY_RE.test(stringBody)) %7B%0A        return true;%0A      %7D%0A    %7D%0A%0A    return false;%0A  %7D%0A%0A
   as

remove code related to proxying now that it is moot