// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

/**
 * @fileoverview Defines common conditions for use with
 * {@link webdriver.WebDriver#wait WebDriver wait}.
 *
 * Sample usage:
 *
 *     driver.get('http://www.google.com/ncr');
 *
 *     var query = driver.wait(until.elementLocated(By.name('q')));
 *     query.sendKeys('webdriver\n');
 *
 *     driver.wait(until.titleIs('webdriver - Google Search'));
 *
 * To define a custom condition, simply call WebDriver.wait with a function
 * that will eventually return a truthy-value (neither null, undefined, false,
 * 0, or the empty string):
 *
 *     driver.wait(function() {
 *       return driver.getTitle().then(function(title) {
 *         return title === 'webdriver - Google Search';
 *       });
 *     }, 1000);
 */

'use strict'

const by = require('./by')
const error = require('./error')
const webdriver = require('./webdriver'),
  Condition = webdriver.Condition,
  WebElementCondition = webdriver.WebElementCondition

/**
 * Creates a condition that will wait until the input driver is able to switch
 * to the designated frame. The target frame may be specified as
 *
 * 1. a numeric index into
 *     [window.frames](https://developer.mozilla.org/en-US/docs/Web/API/Window.frames)
 *     for the currently selected frame.
 * 2. a {@link ./webdriver.WebElement}, which must reference a FRAME or IFRAME
 *     element on the current page.
 * 3. a locator which may be used to first locate a FRAME or IFRAME on the
 *     current page before attempting to switch to it.
 *
 * Upon successful resolution of this condition, the driver will be left
 * focused on the new frame.
 *
 * @param {!(number|./webdriver.WebElement|By|
 *           function(!./webdriver.WebDriver): !./webdriver.WebElement)} frame
 *     The frame identifier.
 * @return {!Condition<boolean>} A new condition.
 */
function ableToSwitchToFrame(frame) {
  let condition
  if (typeof frame === 'number' || frame instanceof webdriver.WebElement) {
    condition = (driver) => attemptToSwitchFrames(driver, frame)
  } else {
    condition = function (driver) {
      let locator = /** @type {!(By|Function)} */ (frame)
      return driver.findElements(locator).then(function (els) {
        if (els.length) {
          return attemptToSwitchFrames(driver, els[0])
        }
      })
    }
  }

  return new Condition('to be able to switch to frame', condition)

  function attemptToSwitchFrames(driver, frame) {
    return driver
      .switchTo()
      .frame(frame)
      .then(
        function () {
          return true
        },
        function (e) {
          if (!(e instanceof error.NoSuchFrameError)) {
            throw e
          }
        }
      )
  }
}

/**
 * Creates a condition that waits for an alert to be opened. Upon success, the
 * returned promise will be fulfilled with the handle for the opened alert.
 *
 * @return {!Condition<!./webdriver.Alert>} The new condition.
 */
function alertIsPresent() {
  return new Condition('for alert to be present', function (driver) {
    return driver
      .switchTo()
      .alert()
      .catch(function (e) {
        if (
          !(
            e instanceof error.NoSuchAlertError ||
            // XXX: Workaround for GeckoDriver error `TypeError: can't convert null
            // to object`. For more details, see
            // https://github.com/SeleniumHQ/selenium/pull/2137
            (e instanceof error.WebDriverError &&
              e.message === `can't convert null to object`)
          )
        ) {
          throw e
        }
      })
  })
}

/**
 * Creates a condition that will wait for the current page's title to match the
 * given value.
 *
 * @param {string} title The expected page title.
 * @return {!Condition<boolean>} The new condition.
 */
function titleIs(title) {
  return new Condition('for title to be ' + JSON.stringify(title), function (
    driver
  ) {
    return driver.getTitle().then(function (t) {
      return t === title
    })
  })
}

/**
 * Creates a condition that will wait for the current page's title to contain
 * the given substring.
 *
 * @param {string} substr The substring that should be present in the page
 *     title.
 * @return {!Condition<boolean>} The new condition.
 */
function titleContains(substr) {
  return new Condition(
    'for title to contain ' + JSON.stringify(substr),
    function (driver) {
      return driver.getTitle().then(function (title) {
        return title.indexOf(substr) !== -1
      })
    }
  )
}

/**
 * Creates a condition that will wait for the current page's title to match the
 * given regular expression.
 *
 * @param {!RegExp} regex The regular expression to test against.
 * @return {!Condition<boolean>} The new condition.
 */
function titleMatches(regex) {
  return new Condition('for title to match ' + regex, function (driver) {
    return driver.getTitle().then(function (title) {
      return regex.test(title)
    })
  })
}

/**
 * Creates a condition that will wait for the current page's url to match the
 * given value.
 *
 * @param {string} url The expected page url.
 * @return {!Condition<boolean>} The new condition.
 */
function urlIs(url) {
  return new Condition('for URL to be ' + JSON.stringify(url), function (
    driver
  ) {
    return driver.getCurrentUrl().then(function (u) {
      return u === url
    })
  })
}

/**
 * Creates a condition that will wait for the current page's url to contain
 * the given substring.
 *
 * @param {string} substrUrl The substring that should be present in the current
 *     URL.
 * @return {!Condition<boolean>} The new condition.
 */
function urlContains(substrUrl) {
  return new Condition(
    'for URL to contain ' + JSON.stringify(substrUrl),
    function (driver) {
      return driver.getCurrentUrl().then(function (url) {
        return url && url.includes(substrUrl)
      })
    }
  )
}

/**
 * Creates a condition that will wait for the current page's url to match the
 * given regular expression.
 *
 * @param {!RegExp} regex The regular expression to test against.
 * @return {!Condition<boolean>} The new condition.
 */
function urlMatches(regex) {
  return new Condition('for URL to match ' + regex, function (driver) {
    return driver.getCurrentUrl().then(function (url) {
      return regex.test(url)
    })
  })
}

/**
 * Creates a condition that will loop until an element is
 * {@link ./webdriver.WebDriver#findElement found} with the given locator.
 *
 * @param {!(By|Function)} locator The locator to use.
 * @return {!WebElementCondition} The new condition.
 */
function elementLocated(locator) {
  locator = by.checkedLocator(locator)
  let locatorStr =
    typeof locator === 'function' ? 'by function()' : locator + ''
  return new WebElementCondition(
    'for element to be located ' + locatorStr,
    function (driver) {
      return driver.findElements(locator).then(function (elements) {
        return elements[0]
      })
    }
  )
}

/**
 * Creates a condition that will loop until at least one element is
 * {@link ./webdriver.WebDriver#findElement found} with the given locator.
 *
 * @param {!(By|Function)} locator The locator to use.
 * @return {!Condition<!Array<!./webdriver.WebElement>>} The new
 *     condition.
 */
function elementsLocated(locator) {
  locator = by.checkedLocator(locator)
  let locatorStr =
    typeof locator === 'function' ? 'by function()' : locator + ''
  return new Condition(
    'for at least one element to be located ' + locatorStr,
    function (driver) {
      return driver.findElements(locator).then(function (elements) {
        return elements.length > 0 ? elements : null
      })
    }
  )
}

/**
 * Creates a condition that will wait for the given element to become stale. An
 * element is considered stale once it is removed from the DOM, or a new page
 * has loaded.
 *
 * @param {!./webdriver.WebElement} element The element that should become stale.
 * @return {!Condition<boolean>} The new condition.
 */
function stalenessOf(element) {
  return new Condition('element to become stale', function () {
    return element.getTagName().then(
      function () {
        return false
      },
      function (e) {
        if (e instanceof error.StaleElementReferenceError) {
          return true
        }
        throw e
      }
    )
  })
}

/**
 * Creates a condition that will wait for the given element to become visible.
 *
 * @param {!./webdriver.WebElement} element The element to test.
 * @return {!WebElementCondition} The new condition.
 * @see ./webdriver.WebDriver#isDisplayed
 */
function elementIsVisible(element) {
  return new WebElementCondition('until element is visible', function () {
    return element.isDisplayed().then((v) => (v ? element : null))
  })
}

/**
 * Creates a condition that will wait for the given element to be in the DOM,
 * yet not visible to the user.
 *
 * @param {!./webdriver.WebElement} element The element to test.
 * @return {!WebElementCondition} The new condition.
 * @see ./webdriver.WebDriver#isDisplayed
 */
function elementIsNotVisible(element) {
  return new WebElementCondition('until element is not visible', function () {
    return element.isDisplayed().then((v) => (v ? null : element))
  })
}

/**
 * Creates a condition that will wait for the given element to be enabled.
 *
 * @param {!./webdriver.WebElement} element The element to test.
 * @return {!WebElementCondition} The new condition.
 * @see webdriver.WebDriver#isEnabled
 */
function elementIsEnabled(element) {
  return new WebElementCondition('until element is enabled', function () {
    return element.isEnabled().then((v) => (v ? element : null))
  })
}

/**
 * Creates a condition that will wait for the given element to be disabled.
 *
 * @param {!./webdriver.WebElement} element The element to test.
 * @return {!WebElementCondition} The new condition.
 * @see webdriver.WebDriver#isEnabled
 */
function elementIsDisabled(element) {
  return new WebElementCondition('until element is disabled', function () {
    return element.isEnabled().then((v) => (v ? null : element))
  })
}

/**
 * Creates a condition that will wait for the given element to be selected.
 * @param {!./webdriver.WebElement} element The element to test.
 * @return {!WebElementCondition} The new condition.
 * @see webdriver.WebDriver#isSelected
 */
function elementIsSelected(element) {
  return new WebElementCondition('until element is selected', function () {
    return element.isSelected().then((v) => (v ? element : null))
  })
}

/**
 * Creates a condition that will wait for the given element to be deselected.
 *
 * @param {!./webdriver.WebElement} element The element to test.
 * @return {!WebElementCondition} The new condition.
 * @see webdriver.WebDriver#isSelected
 */
function elementIsNotSelected(element) {
  return new WebElementCondition('until element is not selected', function () {
    return element.isSelected().then((v) => (v ? null : element))
  })
}

/**
 * Creates a condition that will wait for the given element's
 * {@link webdriver.WebDriver#getText visible text} to match the given
 * {@code text} exactly.
 *
 * @param {!./webdriver.WebElement} element The element to test.
 * @param {string} text The expected text.
 * @return {!WebElementCondition} The new condition.
 * @see webdriver.WebDriver#getText
 */
function elementTextIs(element, text) {
  return new WebElementCondition('until element text is', function () {
    return element.getText().then((t) => (t === text ? element : null))
  })
}

/**
 * Creates a condition that will wait for the given element's
 * {@link webdriver.WebDriver#getText visible text} to contain the given
 * substring.
 *
 * @param {!./webdriver.WebElement} element The element to test.
 * @param {string} substr The substring to search for.
 * @return {!WebElementCondition} The new condition.
 * @see webdriver.WebDriver#getText
 */
function elementTextContains(element, substr) {
  return new WebElementCondition('until element text contains', function () {
    return element
      .getText()
      .then((t) => (t.indexOf(substr) != -1 ? element : null))
  })
}

/**
 * Creates a condition that will wait for the given element's
 * {@link webdriver.WebDriver#getText visible text} to match a regular
 * expression.
 *
 * @param {!./webdriver.WebElement} element The element to test.
 * @param {!RegExp} regex The regular expression to test against.
 * @return {!WebElementCondition} The new condition.
 * @see webdriver.WebDriver#getText
 */
function elementTextMatches(element, regex) {
  return new WebElementCondition('until element text matches', function () {
    return element.getText().then((t) => (regex.test(t) ? element : null))
  })
}

// PUBLIC API

module.exports = {
  elementTextMatches,
  elementTextContains,
  elementTextIs,
  elementIsNotSelected,
  elementIsSelected,
  elementIsDisabled,
  ableToSwitchToFrame,
  elementIsEnabled,
  elementIsNotVisible,
  elementIsVisible,
  stalenessOf,
  elementsLocated,
  elementLocated,
  urlMatches,
  urlContains,
  urlIs,
  titleMatches,
  titleContains,
  alertIsPresent,
  titleIs,
}
