// Type definitions for ow-electron 34.5.5

import { App, BrowserWindow, Event, WebviewTag } from 'electron';
import { errorMonitor } from 'events';

declare namespace overwolf {
  interface OverwolfApp extends App {
    /**
     * Overwolf additional api's
     */
    overwolf: OverwolfApi;
  }

  interface OverwolfApi {
    /**
     * Disable sending any anonymous analytics,
     * this should be call before app.ready
     */
    disableAnonymousAnalytics(): void;

    /**
     * Disable Ads optimization
     */
    disableAdsOptimization(): void;

    /**
     * Opt out from using first party date (email address) for ad targeting
     */
    disableAdsFPD(): void;

    /**
     * Returns true if the current user should be able to update their cmp
     * configurations (i.e. openCMPWindow).
     *
     * Note that this is an async function and should be called with await.
     * The function will never throw an exception - the default value is true.
     */
    isCMPRequired(): Promise<boolean>;

    /**
     * Opens the CMP configuration window - should only be called when
     * isCMPRequired returns true.
     */
    openCMPWindow(options?: CMPWindowOptions): Promise<void>;

    /**
     * Opens the Ads settings configuration window.
     */
    openAdPrivacySettingsWindow(options?: CMPWindowOptions): Promise<void>;

    /**
     * The Overwolf Package Manager instance
     */
    packages: overwolf.packages.OverwolfPackageManager;

    /**
     * Generate a hashed email, to allow for better ad performance,
     * this should be call after app.ready
     * NOTE: the email is not stored! only the hashed email.
     */
    generateUserEmailHashes(email: string): EmailHashes;

    /**
     * Set the user email hashes (see generateUserEmailHashes),
     * this should be call after app.ready
     * See https://www.chromium.org/developers/design-documents/accessibility for more
     * details how to normalize email before creating hash
     */
    setUserEmailHashes(emailHashes: EmailHashes): void;

    /**
     * Client persistence phasing precent
     */
    readonly phasePercent: number;

    /**
     * Overwolf installer provided UTM params
     */
    readonly utmParams: any;
  }

  interface CMPWindowOptions {
    /**
     * Select open tab. The default is 'purposes'
     */
    tab?: 'purposes' | 'features' | 'vendors';

    /**
     * Whether this is a modal window. This only works when the window is a child
     * window. Default is `false`.
     */
    modal?: boolean;

    /**
     * Specify parent window. Default is `null`.
     */
    parent?: BrowserWindow;

    /**
     * Show window in the center of the screen. Default is `true`.
     */
    center?: boolean;

    /**
     * Control the CMP preloader background window
     */
    backgroundColor?: string;

    /**
     * Control the CMP preloader color (spinner)
     */
    preLoaderSpinnerColor?: string;

    /**
     * Control the CMP Window width
     */
    width?: number;

    /**
     * Control the CMP Window height
     */
    height?: number;

    /**
     * Control the CMP Window left pos
     */
    x?: number;

    /**
     * Control the CMP Window top pos
     */
    y?: number;

    /**
     * Overrides the path of the cmp html
     */
    cmpURL?: string;

    /**
     * Cmp html language
     */
    language?: string;
  }

  interface EmailHashes {
    readonly sha1: string;
    readonly sha256: string;
    readonly md5: string;
  }

  /**
   * A utility type for registering to `error` events, that includes the `errorMonitor` type
   */
  type error = 'error' | typeof errorMonitor;

  /**
   * Namespace containing everything related to Overwolf Packages
   */
  namespace packages {
    /**
     * A fake enum for all built-in packIge names
     */
    type PackageName = 'gep' | 'overlay' | 'recorder' | 'utility' | string;

    /**
     * Package info
     */
    interface PackageInfo {
      name: string;
      version: string;
    }

    type PendingUpdatesResult = {
      hasPendingUpdate: boolean;
      details: PackageInfo[];
    };

    /**
     * Overwolf Package Manager interface
     */
    interface OverwolfPackageManager extends NodeJS.EventEmitter {
      /**
       * Register listener for Overwolf Package crashes.
       * Calling `event.preventDefault()` will prevent the package from automatically attempting to re-launch itself.
       *
       * @param {string | symbol} eventName Name of the node event ('crashed')
       * @param {(Event, any[]) => void} listener The listener that will be invoked when this event is fired
       * @returns {this} The current instance of the Overwolf Package Manager
       */
      on(
        eventName: 'crashed',
        listener: (event: Event, canRecover: boolean) => void
      ): this;

      /**
       * Register listener for when an Overwolf Package is ready
       *
       * @param {string | symbol} eventName Name of the node event ('ready')
       * @param {(Event, any[]) => void} listener The listener that will be invoked when this event is fired
       * @returns {this} The current instance of the Overwolf Package Manager
       */
      on(
        eventName: 'ready',
        listener: (event: Event, packageName: PackageName, version: string) => void
      ): this;

      /**
       * Register listener for when an Overwolf Package is ready to update
       *
       * @param {string | symbol} eventName Name of the node event ('package-update-pending')
       * @param {(Event, PackageInfo[]) => void} listener The listener that will be invoked when this event is fired
       * @returns {this} The current instance of the Overwolf Package Manager
       */
      on(
        eventName: 'package-update-pending',
        listener: (event: Event, info: PackageInfo[]) => void
      ): this;

      /**
       * Register listener for when an Overwolf Package updated
       *
       * @param {string | symbol} eventName Name of the node event ('updated')
       * @returns {this} The current instance of the Overwolf Package Manager
       */
      on(
        eventName: 'updated',
        listener: (event: Event, packageName: string, version: string) => void
      ): this;

      /**
       * Register listener for Overwolf Package initialization failures
       *
       * @param {string | symbol} eventName Name of the node event ('failed-to-initialize')
       * @param {(Event, any[]) => void} listener **The listener that will be invoked when this event is fired**
       * @returns {this} The current instance of the Overwolf Package Manager
       */
      on(
        eventName: 'failed-to-initialize',
        listener: (event: Event, packageName: PackageName) => void
      ): this;

      /**
       * Relaunch the Overwolf Package Manager. Call it to force all pending Overwolf Package updates.
       *
       * *The Overwolf Package Manager will automatically relaunch itself if an update is available and no package is currently running.*
       */
      relaunch(): void;

      /**
       * Checks if there are any pending package updates that require a client restart.
       *
       * @returns {PendingUpdatesResult} - Result indicating the status of pending updates.
       */
      hasPendingUpdates(): PendingUpdatesResult;

      /**
       * @property returns the path to the application's logs folder.
       *
       * */
      readonly logsFolderPath: string;

      /**
       * @property {packages.OverwolfGameEventPackage} gep The Game Events Provider Package Instance
       * note: available once 'ready' is fired.
       */
      readonly gep: packages.OverwolfGameEventPackage;
    }

    /**
     * Game Events game detection Event
     */
    export interface GepGameLaunchEvent {
      enable: () => void;
    }

    /**
     * Game Events Package interface
     */
    interface OverwolfGameEventPackage extends NodeJS.EventEmitter {
      /**
       * Returns an array of supported Game Event Features for a game
       *
       * @param {number} gameId Game ID of the targeted game
       * @returns {Promise<string[]>} Promise resolving to an array of supported game features
       */
      getFeatures(gameId: number): Promise<string[]>;

      /**
       * Sets the requires Game Event Features for a given game ID
       *
       * @param {number} gameId Game ID of the targeted game
       * @param {string[] | undefined} features Array of required Game Event Features
       * @returns {Promise<void>} Promise reporting the success of the operation
       */
      setRequiredFeatures(
        gameId: number,
        features: string[] | undefined
      ): Promise<void>;

      /**
       * Returns an array of Game Events supported games
       *
       * @returns {Promise<{
       *  name: string;
       *  id: number;
       * }>} Promise resolving to an array of supported games
       */
      getSupportedGames(): Promise<{
        name: string;
        id: number;
      }>;

      /**
       * Returns the target game's current Game Info
       *
       * @param {number} gameId Game ID of the targeted game
       * @returns {Promise<any>} Promise resolving to the targeted game's current Game Info
       */
      getInfo(gameId: number): Promise<any>;

      /**
       * Register listener for Game Info Updates
       *
       * @param {string | symbol} eventName Name of the node event ('new-info-update')
       * @param {(Event, any[]) => void} listener The listener that will be invoked when this event is fired
       * @returns {this} The current instance of the Overwolf Game Events Package
       */
      on(
        eventName: 'new-info-update',
        listener: (event: Event, gameId: number, data: gep.InfoUpdate) => void
      ): this;

      /**
       * Register listener for New Game Events
       *
       * @param {string | symbol} eventName Name of the node event ('new-game-event')
       * @param {(Event, any[]) => void} listener The listener that will be invoked when this event is fired
       * @returns {this} The current instance of the Overwolf Game Events Package
       */
      on(
        eventName: 'new-game-event',
        listener: (event: Event, gameId: number, data: gep.GameEvent) => void,
      ): this;

      /**
       * Register listener for a game being detected.
       * Calling `event.enable()` to start gep for this game.
       *
       * @param {string | symbol} eventName Name of the node event ('game-detected')
       * @param {(Event, any[]) => void} listener The listener that will be invoked when this event is fired
       * @returns {this} The current instance of the Overwolf Game Events Package
       */
      on(
        eventName: 'game-detected',
        listener: (event: GepGameLaunchEvent, gameId: number, name: string, ...args: any[]) => void,
      ): this;
	  	  
      /**
       * Register listener for a game exit event.
       *
       * @param {string | symbol} eventName Name of the node event ('game-exit')
       * @param {(Event, any[]) => void} listener The listener that will be invoked when this event is fired
       * @returns {this} The current instance of the Overwolf Game Events Package
       */
      on(
        eventName: 'game-exit',
        listener: (event: Event, gameId: number, name: string, pid: number) => void,
      ): this;

      /**
       * Register listener for when a detected game is ran as adminstrator.
       * If this fires, it means the app must also run as adminstrator in order for Game Events to be detected.
       *
       * @param {string | symbol} eventName Name of the node event ('elevated-privileges-required')
       * @param {(Event, any[]) => void} listener The listener that will be invoked when this event is fired
       * @returns {this} The current instance of the Overwolf Game Events Package
       */
      on(
        eventName: 'elevated-privileges-required',
        listener: (event: Event, gameId: number, name: string, pid: number) => void,
      ): this;

      /**
       * Register listener for errors thrown by the Game Events Provider Package
       *
       * @param {string | symbol} eventName Name of the node event ('error' or the `errorMonitor` symbol)
       * @param {(Event, any[]) => void} listener The listener that will be invoked when this event is fired
       * @returns {this} The current instance of the Overwolf Game Events Package
       */
      on(
        eventName: error,
        listener: (event: Event, gameId: number, error: string, ...args: any[]) => void,
      ): this;
    }

    /**
     * Namespace for GEP-related interfaces
     */
    namespace gep {
      /**
       * Interface defining a Game Event's structure
       */
      interface GameEvent {
        /**
         * @property {number} gameId The game id of the game the Event comes from
         */
        gameId: number;
        /**
         * @property {string} feature The feature the Event belongs to
         */
        feature: string;
        /**
         * @property {string} key The name of the Event
         */
        key: string;
        /**
         * @property {any} value The value of the Event
         */
        value: any;
      }

      /**
       * Interface defining an Info Update's structure
       */
      interface InfoUpdate extends GameEvent {
        /**
         * @property {string} category The category the Info Item belongs to
         */
        category: string;
      }
    }
  }

  interface AdviewTag extends HTMLElement {
  }

  namespace Renderer {
    type AdviewTag = overwolf.AdviewTag;
  }
}

interface Document {
  createElement(tagName: 'owadview'): overwolf.AdviewTag;
}
