text: /**
   * Browsers' descriptors
   *
   * The idea of descriptors is simple. You should know about them two simple things:
   * 1. Every descriptor has a method or property called `test` and a `describe` method.
   * 2. Order of descriptors is important.
   *
   * More details:
   * 1. Method or property `test` serves as a way to detect whether the UA string
   * matches some certain browser or not. The `describe` method helps to make a result
   * object with params that show some browser-specific things: name, version, etc.
   * 2. Order of descriptors is important because a Parser goes through them one by one
   * in course. For example, if you insert Chrome's descriptor as the first one,
   * more then a half of browsers will be described as Chrome, because they will pass
   * the Chrome descriptor's test.
   *
   * Descriptor's `test` could be a property with an array of RegExps, where every RegExp
   * will be applied to a UA string to test it whether it matches or not.
   * If a descriptor has two or more regexps in the `test` array it tests them one by one
   * with a logical sum operation. Parser stops if it has found any RegExp that matches the UA.
   *
   * Or `test` could be a method. In that case it gets a Parser instance and should
   * return true/false to get the Parser know if this browser descriptor matches the UA or not.
   */
  
  import {
    getFirstMatch,
    getSecondMatch,
  } from './utils';
  
  const commonVersionIdentifier = /version\/(\d+(\.?_?\d+)+)/i;
  
  const browsersList = [
    /* Opera < 13.0 */
    {
      test: [/opera/i],
      describe(ua) {
        const browser = {
          name: 'Opera',
        };
        const version = getFirstMatch(commonVersionIdentifier, ua) || getFirstMatch(/(?:opera)[\s/](\d+(\.?_?\d+)+)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
  
    /* Opera > 13.0 */
    {
      test: [/opr\/|opios/i],
      describe(ua) {
        const browser = {
          name: 'Opera',
        };
        const version = getFirstMatch(/(?:opr|opios)[\s/](\S+)/i, ua) || getFirstMatch(commonVersionIdentifier, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/SamsungBrowser/i],
      describe(ua) {
        const browser = {
          name: 'Samsung Internet for Android',
        };
        const version = getFirstMatch(commonVersionIdentifier, ua) || getFirstMatch(/(?:SamsungBrowser)[\s/](\d+(\.?_?\d+)+)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/Whale/i],
      describe(ua) {
        const browser = {
          name: 'NAVER Whale Browser',
        };
        const version = getFirstMatch(commonVersionIdentifier, ua) || getFirstMatch(/(?:whale)[\s/](\d+(?:\.\d+)+)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/MZBrowser/i],
      describe(ua) {
        const browser = {
          name: 'MZ Browser',
        };
        const version = getFirstMatch(/(?:MZBrowser)[\s/](\d+(?:\.\d+)+)/i, ua) || getFirstMatch(commonVersionIdentifier, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/focus/i],
      describe(ua) {
        const browser = {
          name: 'Focus',
        };
        const version = getFirstMatch(/(?:focus)[\s/](\d+(?:\.\d+)+)/i, ua) || getFirstMatch(commonVersionIdentifier, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/swing/i],
      describe(ua) {
        const browser = {
          name: 'Swing',
        };
        const version = getFirstMatch(/(?:swing)[\s/](\d+(?:\.\d+)+)/i, ua) || getFirstMatch(commonVersionIdentifier, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/coast/i],
      describe(ua) {
        const browser = {
          name: 'Opera Coast',
        };
        const version = getFirstMatch(commonVersionIdentifier, ua) || getFirstMatch(/(?:coast)[\s/](\d+(\.?_?\d+)+)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/yabrowser/i],
      describe(ua) {
        const browser = {
          name: 'Yandex Browser',
        };
        const version = getFirstMatch(commonVersionIdentifier, ua) || getFirstMatch(/(?:yabrowser)[\s/](\d+(\.?_?\d+)+)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/ucbrowser/i],
      describe(ua) {
        const browser = {
          name: 'UC Browser',
        };
        const version = getFirstMatch(commonVersionIdentifier, ua) || getFirstMatch(/(?:ucbrowser)[\s/](\d+(\.?_?\d+)+)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/Maxthon|mxios/i],
      describe(ua) {
        const browser = {
          name: 'Maxthon',
        };
        const version = getFirstMatch(commonVersionIdentifier, ua) || getFirstMatch(/(?:Maxthon|mxios)[\s/](\d+(\.?_?\d+)+)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/epiphany/i],
      describe(ua) {
        const browser = {
          name: 'Epiphany',
        };
        const version = getFirstMatch(commonVersionIdentifier, ua) || getFirstMatch(/(?:epiphany)[\s/](\d+(\.?_?\d+)+)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/puffin/i],
      describe(ua) {
        const browser = {
          name: 'Puffin',
        };
        const version = getFirstMatch(commonVersionIdentifier, ua) || getFirstMatch(/(?:puffin)[\s/](\d+(\.?_?\d+)+)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/sleipnir/i],
      describe(ua) {
        const browser = {
          name: 'Sleipnir',
        };
        const version = getFirstMatch(commonVersionIdentifier, ua) || getFirstMatch(/(?:sleipnir)[\s/](\d+(\.?_?\d+)+)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/k-meleon/i],
      describe(ua) {
        const browser = {
          name: 'K-Meleon',
        };
        const version = getFirstMatch(commonVersionIdentifier, ua) || getFirstMatch(/(?:k-meleon)[\s/](\d+(\.?_?\d+)+)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/msie|trident/i],
      describe(ua) {
        const browser = {
          name: 'Internet Explorer',
        };
        const version = getFirstMatch(/(?:msie |rv:)(\d+(\.?_?\d+)+)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/edg([ea]|ios)/i],
      describe(ua) {
        const browser = {
          name: 'Microsoft Edge',
        };
  
        const version = getSecondMatch(/edg([ea]|ios)\/(\d+(\.?_?\d+)+)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/vivaldi/i],
      describe(ua) {
        const browser = {
          name: 'Vivaldi',
        };
        const version = getFirstMatch(/vivaldi\/(\d+(\.?_?\d+)+)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/seamonkey/i],
      describe(ua) {
        const browser = {
          name: 'SeaMonkey',
        };
        const version = getFirstMatch(/seamonkey\/(\d+(\.?_?\d+)+)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/sailfish/i],
      describe(ua) {
        const browser = {
          name: 'Sailfish',
        };
  
        const version = getFirstMatch(/sailfish\s?browser\/(\d+(\.\d+)?)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/silk/i],
      describe(ua) {
        const browser = {
          name: 'Amazon Silk',
        };
        const version = getFirstMatch(/silk\/(\d+(\.?_?\d+)+)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/phantom/i],
      describe(ua) {
        const browser = {
          name: 'PhantomJS',
        };
        const version = getFirstMatch(/phantomjs\/(\d+(\.?_?\d+)+)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/slimerjs/i],
      describe(ua) {
        const browser = {
          name: 'SlimerJS',
        };
        const version = getFirstMatch(/slimerjs\/(\d+(\.?_?\d+)+)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/blackberry|\bbb\d+/i, /rim\stablet/i],
      describe(ua) {
        const browser = {
          name: 'BlackBerry',
        };
        const version = getFirstMatch(commonVersionIdentifier, ua) || getFirstMatch(/blackberry[\d]+\/(\d+(\.?_?\d+)+)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/(web|hpw)[o0]s/i],
      describe(ua) {
        const browser = {
          name: 'WebOS Browser',
        };
        const version = getFirstMatch(commonVersionIdentifier, ua) || getFirstMatch(/w(?:eb)?[o0]sbrowser\/(\d+(\.?_?\d+)+)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/bada/i],
      describe(ua) {
        const browser = {
          name: 'Bada',
        };
        const version = getFirstMatch(/dolfin\/(\d+(\.?_?\d+)+)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/tizen/i],
      describe(ua) {
        const browser = {
          name: 'Tizen',
        };
        const version = getFirstMatch(/(?:tizen\s?)?browser\/(\d+(\.?_?\d+)+)/i, ua) || getFirstMatch(commonVersionIdentifier, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/qupzilla/i],
      describe(ua) {
        const browser = {
          name: 'QupZilla',
        };
        const version = getFirstMatch(/(?:qupzilla)[\s/](\d+(\.?_?\d+)+)/i, ua) || getFirstMatch(commonVersionIdentifier, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/firefox|iceweasel|fxios/i],
      describe(ua) {
        const browser = {
          name: 'Firefox',
        };
        const version = getFirstMatch(/(?:firefox|iceweasel|fxios)[\s/](\d+(\.?_?\d+)+)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/chromium/i],
      describe(ua) {
        const browser = {
          name: 'Chromium',
        };
        const version = getFirstMatch(/(?:chromium)[\s/](\d+(\.?_?\d+)+)/i, ua) || getFirstMatch(commonVersionIdentifier, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
    {
      test: [/chrome|crios|crmo/i],
      describe(ua) {
        const browser = {
          name: 'Chrome',
        };
        const version = getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.?_?\d+)+)/i, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
  
    /* Android Browser */
    {
      test(parser) {
        const notLikeAndroid = !parser.test(/like android/i);
        const butAndroid = parser.test(/android/i);
        return notLikeAndroid && butAndroid;
      },
      describe(ua) {
        const browser = {
          name: 'Android Browser',
        };
        const version = getFirstMatch(commonVersionIdentifier, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
  
    /* Safari */
    {
      test: [/safari|applewebkit/i],
      describe(ua) {
        const browser = {
          name: 'Safari',
        };
        const version = getFirstMatch(commonVersionIdentifier, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
  
    /* Googlebot */
    {
      test: [/googlebot/i],
      describe(ua) {
        const browser = {
          name: 'Googlebot',
        };
        const version = getFirstMatch(/googlebot\/(\d+(\.\d+))/i, ua) || getFirstMatch(commonVersionIdentifier, ua);
  
        if (version) {
          browser.version = version;
        }
  
        return browser;
      },
    },
  
    /* Something else */
    {
      test: [/.*/i],
      describe(ua) {
        return {
          name: getFirstMatch(/^(.*)\/(.*) /, ua),
          version: getSecondMatch(/^(.*)\/(.*) /, ua),
        };
      },
    },
  ];
  
  export default browsersList;
  