/*!
 * SPDX-License-Identifier: Unlicense
 * This file was automatically generated by https://github.com/yt-dlp/ejs
 */
var jsc = (function (meriyah, astring) {
  'use strict';
  function matchesStructure(obj, structure) {
    if (Array.isArray(structure)) {
      if (!Array.isArray(obj)) {
        return false;
      }
      return (
        structure.length === obj.length &&
        structure.every((value, index) => matchesStructure(obj[index], value))
      );
    }
    if (typeof structure === 'object') {
      if (!obj) {
        return !structure;
      }
      if ('or' in structure) {
        return structure.or.some((node) => matchesStructure(obj, node));
      }
      if ('anykey' in structure && Array.isArray(structure.anykey)) {
        const haystack = Array.isArray(obj) ? obj : Object.values(obj);
        return structure.anykey.every((value) =>
          haystack.some((el) => matchesStructure(el, value)),
        );
      }
      for (const [key, value] of Object.entries(structure)) {
        if (!matchesStructure(obj[key], value)) {
          return false;
        }
      }
      return true;
    }
    return structure === obj;
  }
  function isOneOf(value, ...of) {
    return of.includes(value);
  }
  function _optionalChain$2(ops) {
    let lastAccessLHS = undefined;
    let value = ops[0];
    let i = 1;
    while (i < ops.length) {
      const op = ops[i];
      const fn = ops[i + 1];
      i += 2;
      if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) {
        return undefined;
      }
      if (op === 'access' || op === 'optionalAccess') {
        lastAccessLHS = value;
        value = fn(value);
      } else if (op === 'call' || op === 'optionalCall') {
        value = fn((...args) => value.call(lastAccessLHS, ...args));
        lastAccessLHS = undefined;
      }
    }
    return value;
  }
  const nsig = {
    type: 'CallExpression',
    callee: { or: [{ type: 'Identifier' }, { type: 'SequenceExpression' }] },
    arguments: [
      {},
      {
        type: 'CallExpression',
        callee: { type: 'Identifier', name: 'decodeURIComponent' },
        arguments: [{}],
      },
    ],
  };
  const nsigAssignment = {
    type: 'AssignmentExpression',
    left: { type: 'Identifier' },
    operator: '=',
    right: nsig,
  };
  const nsigDeclarator = {
    type: 'VariableDeclarator',
    id: { type: 'Identifier' },
    init: nsig,
  };
  const logicalExpression = {
    type: 'ExpressionStatement',
    expression: {
      type: 'LogicalExpression',
      left: { type: 'Identifier' },
      right: {
        type: 'SequenceExpression',
        expressions: [
          {
            type: 'AssignmentExpression',
            left: { type: 'Identifier' },
            operator: '=',
            right: {
              type: 'CallExpression',
              callee: { type: 'Identifier' },
              arguments: {
                or: [
                  [
                    {
                      type: 'CallExpression',
                      callee: {
                        type: 'Identifier',
                        name: 'decodeURIComponent',
                      },
                      arguments: [{ type: 'Identifier' }],
                      optional: false,
                    },
                  ],
                  [
                    { type: 'Literal' },
                    {
                      type: 'CallExpression',
                      callee: {
                        type: 'Identifier',
                        name: 'decodeURIComponent',
                      },
                      arguments: [{ type: 'Identifier' }],
                      optional: false,
                    },
                  ],
                  [
                    { type: 'Literal' },
                    { type: 'Literal' },
                    {
                      type: 'CallExpression',
                      callee: {
                        type: 'Identifier',
                        name: 'decodeURIComponent',
                      },
                      arguments: [{ type: 'Identifier' }],
                      optional: false,
                    },
                  ],
                ],
              },
              optional: false,
            },
          },
          { type: 'CallExpression' },
        ],
      },
      operator: '&&',
    },
  };
  const identifier$1 = {
    or: [
      {
        type: 'ExpressionStatement',
        expression: {
          type: 'AssignmentExpression',
          operator: '=',
          left: { or: [{ type: 'Identifier' }, { type: 'MemberExpression' }] },
          right: { type: 'FunctionExpression' },
        },
      },
      { type: 'FunctionDeclaration' },
      {
        type: 'VariableDeclaration',
        declarations: {
          anykey: [
            {
              type: 'VariableDeclarator',
              init: { type: 'FunctionExpression' },
            },
          ],
        },
      },
    ],
  };
  function extract$1(node) {
    const blocks = [];
    if (matchesStructure(node, identifier$1)) {
      if (
        node.type === 'ExpressionStatement' &&
        node.expression.type === 'AssignmentExpression' &&
        node.expression.right.type === 'FunctionExpression' &&
        node.expression.right.params.length >= 3
      ) {
        blocks.push(node.expression.right.body);
      } else if (node.type === 'VariableDeclaration') {
        for (const decl of node.declarations) {
          if (
            _optionalChain$2([
              decl,
              'access',
              (_) => _.init,
              'optionalAccess',
              (_2) => _2.type,
            ]) === 'FunctionExpression' &&
            decl.init.params.length >= 3
          ) {
            blocks.push(decl.init.body);
          }
        }
      } else if (
        node.type === 'FunctionDeclaration' &&
        node.params.length >= 3
      ) {
        blocks.push(node.body);
      } else {
        return null;
      }
    } else if (
      node.type === 'ExpressionStatement' &&
      node.expression.type === 'SequenceExpression'
    ) {
      for (const expr of node.expression.expressions) {
        if (
          expr.type === 'AssignmentExpression' &&
          expr.right.type === 'FunctionExpression' &&
          expr.right.params.length === 3
        ) {
          blocks.push(expr.right.body);
        }
      }
    } else {
      return null;
    }
    for (const block of blocks) {
      let call = null;
      for (const stmt of block.body) {
        if (matchesStructure(stmt, logicalExpression)) {
          if (
            stmt.type === 'ExpressionStatement' &&
            stmt.expression.type === 'LogicalExpression' &&
            stmt.expression.right.type === 'SequenceExpression' &&
            stmt.expression.right.expressions[0].type ===
              'AssignmentExpression' &&
            stmt.expression.right.expressions[0].right.type === 'CallExpression'
          ) {
            call = stmt.expression.right.expressions[0].right;
          }
        } else if (stmt.type === 'IfStatement') {
          let consequent = stmt.consequent;
          while (consequent.type === 'LabeledStatement') {
            consequent = consequent.body;
          }
          if (consequent.type !== 'BlockStatement') {
            continue;
          }
          for (const n of consequent.body) {
            if (n.type !== 'VariableDeclaration') {
              continue;
            }
            for (const decl of n.declarations) {
              if (
                matchesStructure(decl, nsigDeclarator) &&
                _optionalChain$2([
                  decl,
                  'access',
                  (_3) => _3.init,
                  'optionalAccess',
                  (_4) => _4.type,
                ]) === 'CallExpression'
              ) {
                call = decl.init;
                break;
              }
            }
            if (call) {
              break;
            }
          }
        } else if (stmt.type === 'ExpressionStatement') {
          if (
            stmt.expression.type !== 'LogicalExpression' ||
            stmt.expression.operator !== '&&' ||
            stmt.expression.right.type !== 'SequenceExpression'
          ) {
            continue;
          }
          for (const expr of stmt.expression.right.expressions) {
            if (matchesStructure(expr, nsigAssignment) && expr.type) {
              if (
                expr.type === 'AssignmentExpression' &&
                expr.right.type === 'CallExpression'
              ) {
                call = expr.right;
                break;
              }
            }
          }
        }
        if (call) {
          break;
        }
      }
      if (!call) {
        continue;
      }
      return {
        type: 'ArrowFunctionExpression',
        params: [{ type: 'Identifier', name: 'sig' }],
        body: {
          type: 'CallExpression',
          callee: call.callee,
          arguments: call.arguments.map((arg) => {
            if (
              arg.type === 'CallExpression' &&
              arg.callee.type === 'Identifier' &&
              arg.callee.name === 'decodeURIComponent'
            ) {
              return { type: 'Identifier', name: 'sig' };
            }
            return arg;
          }),
          optional: false,
        },
        async: false,
        expression: false,
        generator: false,
      };
    }
    return null;
  }
  function _optionalChain$1(ops) {
    let lastAccessLHS = undefined;
    let value = ops[0];
    let i = 1;
    while (i < ops.length) {
      const op = ops[i];
      const fn = ops[i + 1];
      i += 2;
      if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) {
        return undefined;
      }
      if (op === 'access' || op === 'optionalAccess') {
        lastAccessLHS = value;
        value = fn(value);
      } else if (op === 'call' || op === 'optionalCall') {
        value = fn((...args) => value.call(lastAccessLHS, ...args));
        lastAccessLHS = undefined;
      }
    }
    return value;
  }
  const identifier = {
    or: [
      {
        type: 'VariableDeclaration',
        kind: 'var',
        declarations: {
          anykey: [
            {
              type: 'VariableDeclarator',
              id: { type: 'Identifier' },
              init: {
                type: 'ArrayExpression',
                elements: [{ type: 'Identifier' }],
              },
            },
          ],
        },
      },
      {
        type: 'ExpressionStatement',
        expression: {
          type: 'AssignmentExpression',
          left: { type: 'Identifier' },
          operator: '=',
          right: {
            type: 'ArrayExpression',
            elements: [{ type: 'Identifier' }],
          },
        },
      },
    ],
  };
  const catchBlockBody = [
    {
      type: 'ReturnStatement',
      argument: {
        type: 'BinaryExpression',
        left: {
          type: 'MemberExpression',
          object: { type: 'Identifier' },
          computed: true,
          property: { type: 'Literal' },
          optional: false,
        },
        right: { type: 'Identifier' },
        operator: '+',
      },
    },
  ];
  function extract(node) {
    if (!matchesStructure(node, identifier)) {
      let name = null;
      let block = null;
      switch (node.type) {
        case 'ExpressionStatement': {
          if (
            node.expression.type === 'AssignmentExpression' &&
            node.expression.left.type === 'Identifier' &&
            node.expression.right.type === 'FunctionExpression' &&
            node.expression.right.params.length === 1
          ) {
            name = node.expression.left.name;
            block = node.expression.right.body;
          }
          break;
        }
        case 'FunctionDeclaration': {
          if (node.params.length === 1) {
            name = _optionalChain$1([
              node,
              'access',
              (_) => _.id,
              'optionalAccess',
              (_2) => _2.name,
            ]);
            block = node.body;
          }
          break;
        }
      }
      if (!block || !name) {
        return null;
      }
      const tryNode = block.body.at(-2);
      if (
        _optionalChain$1([tryNode, 'optionalAccess', (_3) => _3.type]) !==
          'TryStatement' ||
        _optionalChain$1([
          tryNode,
          'access',
          (_4) => _4.handler,
          'optionalAccess',
          (_5) => _5.type,
        ]) !== 'CatchClause'
      ) {
        return null;
      }
      const catchBody = tryNode.handler.body.body;
      if (matchesStructure(catchBody, catchBlockBody)) {
        return makeSolverFuncFromName(name);
      }
      return null;
    }
    if (node.type === 'VariableDeclaration') {
      for (const declaration of node.declarations) {
        if (
          declaration.type !== 'VariableDeclarator' ||
          !declaration.init ||
          declaration.init.type !== 'ArrayExpression' ||
          declaration.init.elements.length !== 1
        ) {
          continue;
        }
        const [firstElement] = declaration.init.elements;
        if (firstElement && firstElement.type === 'Identifier') {
          return makeSolverFuncFromName(firstElement.name);
        }
      }
    } else if (node.type === 'ExpressionStatement') {
      const expr = node.expression;
      if (
        expr.type === 'AssignmentExpression' &&
        expr.left.type === 'Identifier' &&
        expr.operator === '=' &&
        expr.right.type === 'ArrayExpression' &&
        expr.right.elements.length === 1
      ) {
        const [firstElement] = expr.right.elements;
        if (firstElement && firstElement.type === 'Identifier') {
          return makeSolverFuncFromName(firstElement.name);
        }
      }
    }
    return null;
  }
  function makeSolverFuncFromName(name) {
    return {
      type: 'ArrowFunctionExpression',
      params: [{ type: 'Identifier', name: 'n' }],
      body: {
        type: 'CallExpression',
        callee: { type: 'Identifier', name: name },
        arguments: [{ type: 'Identifier', name: 'n' }],
        optional: false,
      },
      async: false,
      expression: false,
      generator: false,
    };
  }
  const setupNodes = meriyah.parse(
    `\nif (typeof globalThis.XMLHttpRequest === "undefined") {\n    globalThis.XMLHttpRequest = { prototype: {} };\n}\nconst window = Object.create(null);\nif (typeof URL === "undefined") {\n    window.location = {\n        hash: "",\n        host: "www.youtube.com",\n        hostname: "www.youtube.com",\n        href: "https://www.youtube.com/watch?v=yt-dlp-wins",\n        origin: "https://www.youtube.com",\n        password: "",\n        pathname: "/watch",\n        port: "",\n        protocol: "https:",\n        search: "?v=yt-dlp-wins",\n        username: "",\n    };\n} else {\n    window.location = new URL("https://www.youtube.com/watch?v=yt-dlp-wins");\n}\nif (typeof globalThis.document === "undefined") {\n    globalThis.document = Object.create(null);\n}\nif (typeof globalThis.navigator === "undefined") {\n    globalThis.navigator = Object.create(null);\n}\nif (typeof globalThis.self === "undefined") {\n    globalThis.self = globalThis;\n}\n`,
  ).body;
  function _optionalChain(ops) {
    let lastAccessLHS = undefined;
    let value = ops[0];
    let i = 1;
    while (i < ops.length) {
      const op = ops[i];
      const fn = ops[i + 1];
      i += 2;
      if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) {
        return undefined;
      }
      if (op === 'access' || op === 'optionalAccess') {
        lastAccessLHS = value;
        value = fn(value);
      } else if (op === 'call' || op === 'optionalCall') {
        value = fn((...args) => value.call(lastAccessLHS, ...args));
        lastAccessLHS = undefined;
      }
    }
    return value;
  }
  function preprocessPlayer(data) {
    const program = meriyah.parse(data);
    const plainStatements = modifyPlayer(program);
    const solutions = getSolutions(plainStatements);
    for (const [name, options] of Object.entries(solutions)) {
      plainStatements.push({
        type: 'ExpressionStatement',
        expression: {
          type: 'AssignmentExpression',
          operator: '=',
          left: {
            type: 'MemberExpression',
            computed: false,
            object: { type: 'Identifier', name: '_result' },
            property: { type: 'Identifier', name: name },
            optional: false,
          },
          right: multiTry(options),
        },
      });
    }
    program.body.splice(0, 0, ...setupNodes);
    return astring.generate(program);
  }
  function modifyPlayer(program) {
    const body = program.body;
    const block = (() => {
      switch (body.length) {
        case 1: {
          const func = body[0];
          if (
            _optionalChain([func, 'optionalAccess', (_) => _.type]) ===
              'ExpressionStatement' &&
            func.expression.type === 'CallExpression' &&
            func.expression.callee.type === 'MemberExpression' &&
            func.expression.callee.object.type === 'FunctionExpression'
          ) {
            return func.expression.callee.object.body;
          }
          break;
        }
        case 2: {
          const func = body[1];
          if (
            _optionalChain([func, 'optionalAccess', (_2) => _2.type]) ===
              'ExpressionStatement' &&
            func.expression.type === 'CallExpression' &&
            func.expression.callee.type === 'FunctionExpression'
          ) {
            const block = func.expression.callee.body;
            block.body.splice(0, 1);
            return block;
          }
          break;
        }
      }
      throw 'unexpected structure';
    })();
    block.body = block.body.filter((node) => {
      if (node.type === 'ExpressionStatement') {
        if (node.expression.type === 'AssignmentExpression') {
          return true;
        }
        return node.expression.type === 'Literal';
      }
      return true;
    });
    return block.body;
  }
  function getSolutions(statements) {
    const found = { n: [], sig: [] };
    for (const statement of statements) {
      const n = extract(statement);
      if (n) {
        found.n.push(n);
      }
      const sig = extract$1(statement);
      if (sig) {
        found.sig.push(sig);
      }
    }
    return found;
  }
  function getFromPrepared(code) {
    const resultObj = { n: null, sig: null };
    Function('_result', code)(resultObj);
    return resultObj;
  }
  function multiTry(generators) {
    return {
      type: 'ArrowFunctionExpression',
      params: [{ type: 'Identifier', name: '_input' }],
      body: {
        type: 'BlockStatement',
        body: [
          {
            type: 'VariableDeclaration',
            kind: 'const',
            declarations: [
              {
                type: 'VariableDeclarator',
                id: { type: 'Identifier', name: '_results' },
                init: {
                  type: 'NewExpression',
                  callee: { type: 'Identifier', name: 'Set' },
                  arguments: [],
                },
              },
            ],
          },
          {
            type: 'ForOfStatement',
            left: {
              type: 'VariableDeclaration',
              kind: 'const',
              declarations: [
                {
                  type: 'VariableDeclarator',
                  id: { type: 'Identifier', name: '_generator' },
                  init: null,
                },
              ],
            },
            right: { type: 'ArrayExpression', elements: generators },
            body: {
              type: 'BlockStatement',
              body: [
                {
                  type: 'TryStatement',
                  block: {
                    type: 'BlockStatement',
                    body: [
                      {
                        type: 'ExpressionStatement',
                        expression: {
                          type: 'CallExpression',
                          callee: {
                            type: 'MemberExpression',
                            object: { type: 'Identifier', name: '_results' },
                            computed: false,
                            property: { type: 'Identifier', name: 'add' },
                            optional: false,
                          },
                          arguments: [
                            {
                              type: 'CallExpression',
                              callee: {
                                type: 'Identifier',
                                name: '_generator',
                              },
                              arguments: [
                                { type: 'Identifier', name: '_input' },
                              ],
                              optional: false,
                            },
                          ],
                          optional: false,
                        },
                      },
                    ],
                  },
                  handler: {
                    type: 'CatchClause',
                    param: null,
                    body: { type: 'BlockStatement', body: [] },
                  },
                  finalizer: null,
                },
              ],
            },
            await: false,
          },
          {
            type: 'IfStatement',
            test: {
              type: 'UnaryExpression',
              operator: '!',
              argument: {
                type: 'MemberExpression',
                object: { type: 'Identifier', name: '_results' },
                computed: false,
                property: { type: 'Identifier', name: 'size' },
                optional: false,
              },
              prefix: true,
            },
            consequent: {
              type: 'BlockStatement',
              body: [
                {
                  type: 'ThrowStatement',
                  argument: {
                    type: 'TemplateLiteral',
                    expressions: [],
                    quasis: [
                      {
                        type: 'TemplateElement',
                        value: { cooked: 'no solutions', raw: 'no solutions' },
                        tail: true,
                      },
                    ],
                  },
                },
              ],
            },
            alternate: null,
          },
          {
            type: 'IfStatement',
            test: {
              type: 'BinaryExpression',
              left: {
                type: 'MemberExpression',
                object: { type: 'Identifier', name: '_results' },
                computed: false,
                property: { type: 'Identifier', name: 'size' },
                optional: false,
              },
              right: { type: 'Literal', value: 1 },
              operator: '!==',
            },
            consequent: {
              type: 'BlockStatement',
              body: [
                {
                  type: 'ThrowStatement',
                  argument: {
                    type: 'TemplateLiteral',
                    expressions: [
                      {
                        type: 'CallExpression',
                        callee: {
                          type: 'MemberExpression',
                          object: { type: 'Identifier', name: '_results' },
                          computed: false,
                          property: { type: 'Identifier', name: 'join' },
                          optional: false,
                        },
                        arguments: [{ type: 'Literal', value: ', ' }],
                        optional: false,
                      },
                    ],
                    quasis: [
                      {
                        type: 'TemplateElement',
                        value: {
                          cooked: 'invalid solutions: ',
                          raw: 'invalid solutions: ',
                        },
                        tail: false,
                      },
                      {
                        type: 'TemplateElement',
                        value: { cooked: '', raw: '' },
                        tail: true,
                      },
                    ],
                  },
                },
              ],
            },
            alternate: null,
          },
          {
            type: 'ReturnStatement',
            argument: {
              type: 'MemberExpression',
              object: {
                type: 'CallExpression',
                callee: {
                  type: 'MemberExpression',
                  object: {
                    type: 'CallExpression',
                    callee: {
                      type: 'MemberExpression',
                      object: { type: 'Identifier', name: '_results' },
                      computed: false,
                      property: { type: 'Identifier', name: 'values' },
                      optional: false,
                    },
                    arguments: [],
                    optional: false,
                  },
                  computed: false,
                  property: { type: 'Identifier', name: 'next' },
                  optional: false,
                },
                arguments: [],
                optional: false,
              },
              computed: false,
              property: { type: 'Identifier', name: 'value' },
              optional: false,
            },
          },
        ],
      },
      async: false,
      expression: false,
      generator: false,
    };
  }
  function main(input) {
    const preprocessedPlayer =
      input.type === 'player'
        ? preprocessPlayer(input.player)
        : input.preprocessed_player;
    const solvers = getFromPrepared(preprocessedPlayer);
    const responses = input.requests.map((input) => {
      if (!isOneOf(input.type, 'n', 'sig')) {
        return { type: 'error', error: `Unknown request type: ${input.type}` };
      }
      const solver = solvers[input.type];
      if (!solver) {
        return {
          type: 'error',
          error: `Failed to extract ${input.type} function`,
        };
      }
      try {
        return {
          type: 'result',
          data: Object.fromEntries(
            input.challenges.map((challenge) => [challenge, solver(challenge)]),
          ),
        };
      } catch (error) {
        return {
          type: 'error',
          error:
            error instanceof Error
              ? `${error.message}\n${error.stack}`
              : `${error}`,
        };
      }
    });
    const output = { type: 'result', responses: responses };
    if (input.type === 'player' && input.output_preprocessed) {
      output.preprocessed_player = preprocessedPlayer;
    }
    return output;
  }
  return main;
})(meriyah, astring);
