'use strict';

const request = require('./utils/request');
const memoize = require('./utils/memoize');
const cheerio = require('cheerio');
const getParseList = require('./utils/parseList');

function getClp (html) {
  return html.match(/\?clp=(.*?)&amp;/)[1].replace(/%3D/g, '=');
}

function getNextToken (html) {
  // extract the token for the next page request
  // for the record, I hate regexps
  // const s = html.match(/\\42(GAE.+?)\\42/);
  const s = html.match(/\\x22-p6(.*?):S:(.*?)\\x22/g);
  if (!s) {
    return undefined;
  }
  return s[0].replace(/\\\\u003d/g, '=').replace(/\\x22/g, '');
}

/*
 * Extract navigation tokens for next pages, parse results and call
 * `checkFinished` to repeat the process with next page if necessary.
 */
function processAndRecur (html, opts, savedApps) {
  const nextToken = getNextToken(html);
  const clp = getClp(html); // TODO this doesn't change could be calculated just once

  const $ = cheerio.load(html);
  return getParseList(opts)($)
    .then((newApps) => savedApps.concat(newApps))
    .then((apps) => checkFinished(opts, apps, nextToken, clp));
}

/*
 * If already have requested results or there are no more pages, return current
 * app list, otherwise request the ajax endpoint of the next page and process
 * the results.
 */
function checkFinished (opts, savedApps, nextToken, clp) {
  if (savedApps.length >= opts.num || !nextToken) {
    return savedApps.slice(0, opts.num);
  }

  const requestOptions = {
    url: 'https://play.google.com/store/apps/collection/search_results_cluster_apps',
    method: 'POST',
    form: {
      num: savedApps.length === 49 ? 0 : 48, // confirm if always 48 works
      start: savedApps.length - 49,
      pagTok: nextToken,
      clp,
      pagtt: 3,
      hl: opts.lang,
      gl: opts.country
    },
    proxy: opts.proxy
  };

  return request(requestOptions, opts.throttle)
    .then((html) => processAndRecur(html, opts, savedApps));
}

/*
 * Make the first search request as in the browser and call `checkfinished` to
 * process the next pages.
 */
function initialRequest (opts) {
  // sometimes the first result page is a cluster of subsections,
  // need to skip to the full results page
  function skipClusterPage (html) {
    const match = html.match(/href="\/store\/apps\/collection\/search_collection_more_results_cluster?(.*?)"/);
    if (match) {
      const innerUrl = 'https://play.google.com/' + match[0].split(/"/)[1];
      return request({
        url: innerUrl,
        proxy: opts.proxy
      }, opts.throttle);
    }
    return html;
  }

  const url = `https://play.google.com/store/search?c=apps&q=${opts.term}&hl=${opts.lang}&gl=${opts.country}&price=${opts.price}`;
  return request({url, proxy: opts.proxy}, opts.throttle)
    .then(skipClusterPage)
    .then((html) => processAndRecur(html, opts, []));
}

function getPriceGoogleValue (value) {
  switch (value.toLowerCase()) {
    case 'free':
      return 1;
    case 'paid':
      return 2;
    case 'all':
    default:
      return 0;
  }
}

function search (opts) {
  return new Promise(function (resolve, reject) {
    if (!opts || !opts.term) {
      throw Error('Search term missing');
    }

    if (opts.num && opts.num > 250) {
      throw Error("The number of results can't exceed 250");
    }

    opts = {
      term: encodeURIComponent(opts.term),
      lang: opts.lang || 'en',
      country: opts.country || 'us',
      num: opts.num || 20,
      fullDetail: opts.fullDetail,
      price: opts.price ? getPriceGoogleValue(opts.price) : 0,
      throttle: opts.throttle,
      proxy: opts.proxy
    };

    initialRequest(opts)
      .then(resolve)
      .catch(reject);
  });
}

module.exports = memoize(search);

@@ -245,13 +245,10 @@
 .*?)
-&amp;
+%22%3E
 /)%5B1

Use new regex for getting clp