"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const shaka_player_1 = require("@internal/shaka-player");
const elements_1 = require("./elements");
const DEFAULT_SPINNER_TIMEOUT = 2000;
const eventList = [
    "abort",
    "canplay",
    "canplaythrough",
    "durationchange",
    "emptied",
    "encrypted",
    "ended",
    "error",
    "loadstart",
    "progress",
    "ratechange",
    "seeked",
    "seeking",
    "stalled",
    "suspend",
    "timeupdate",
    "waiting",
];
const videoConfig = {
    addBigPlayButton: false,
    addSeekBar: true,
    controlPanelElements: [
        "play_pause",
        "current_time",
        "spacer",
        "total_time",
        "captions",
        "mute_popover",
        "report",
        "fullscreen_button",
    ],
};
class Video {
    isPlaylist(source) {
        const type = source.type && source.type.toLowerCase();
        const src = source.src;
        if (type === "dash" || type === "hls") {
            return true;
        }
        else if (source.src) {
            return (src.indexOf(".mpd") === src.length - 5 ||
                src.indexOf(".m3u8") === src.length - 6);
        }
        return false;
    }
    handleResize() {
        if (!this.input.width && this.video) {
            const { width: containerWidth } = this.root.getBoundingClientRect();
            this.containerEl.setAttribute("width", containerWidth.toString());
            this.alignSeekbar();
        }
    }
    alignSeekbar() {
        if (this.el) {
            const buttonPanel = this.el.querySelector(".shaka-controls-button-panel");
            const spacer = buttonPanel.querySelector(".shaka-spacer");
            const rangeContainer = this.el.querySelector(".shaka-range-container");
            const buttonPanelRect = buttonPanel.getBoundingClientRect();
            const spacerRect = spacer.getBoundingClientRect();
            rangeContainer.style.marginRight = `${buttonPanelRect.right - spacerRect.right}px`;
            rangeContainer.style.marginLeft = `${spacerRect.left - buttonPanelRect.left}px`;
        }
    }
    handlePause(originalEvent) {
        // On IOS, the controls force showing up if the video exist fullscreen while playing.
        // This forces the controls to always hide
        this.video.controls = false;
        this.emit("pause", { originalEvent, player: this.player });
        this.alignSeekbar();
    }
    handlePlaying(originalEvent) {
        this.showControls();
        this.alignSeekbar();
        if (this.input.playView === "fullscreen") {
            this.video.requestFullscreen();
        }
        this.state.played = true;
        this.emit("play", { originalEvent, player: this.player });
    }
    handleVolumeChange(originalEvent) {
        this.emit("volume-change", {
            originalEvent,
            volume: this.video.volume,
            muted: this.video.muted,
        });
    }
    handleError(err) {
        this.state.failed = true;
        this.state.isLoaded = true;
        if (this.ui) {
            this.ui.configure({
                addBigPlayButton: false,
            });
        }
        this.emit("load-error", err);
    }
    showControls() {
        const copyConfig = Object.assign({}, videoConfig);
        copyConfig.controlPanelElements = [...videoConfig.controlPanelElements];
        if (this.state.volumeSlider === true) {
            const insertAt = copyConfig.controlPanelElements.length - 2 > 0
                ? copyConfig.controlPanelElements.length - 2
                : copyConfig.controlPanelElements.length;
            copyConfig.controlPanelElements.splice(insertAt, 0, "volume");
        }
        this.ui.configure(copyConfig);
        this.video.controls = false;
    }
    takeAction() {
        switch (this.state.action) {
            case "play":
                this.video.play();
                break;
            case "pause":
                this.video.pause();
                break;
            default:
        }
    }
    onInput(input) {
        var _a, _b;
        if (this.video) {
            if (input.width || input.height) {
                this.containerEl.style.width = `${input.width}px`;
            }
            this.video.volume = (_a = input.volume) !== null && _a !== void 0 ? _a : 0;
            this.video.muted = !!input.muted;
        }
        // Check if action is changed
        if (this.state.action !== input.action) {
            this.state.action = (_b = input.action) !== null && _b !== void 0 ? _b : "";
            this.takeAction();
        }
        if (input.volumeSlider === true) {
            this.state.volumeSlider = input.volumeSlider;
        }
    }
    onCreate() {
        this.state = {
            volumeSlider: false,
            action: "",
            isLoaded: true,
            failed: false,
            played: false,
        };
    }
    _addTextTracks() {
        (this.input.clip || []).forEach((track) => {
            this.player.addTextTrack(track.src, track.srclang, track.kind);
        });
        const [track] = this.player.getTextTracks();
        if (track) {
            this.player.selectTextTrack(track.id); // => this finds the id and everythings fine but it does nothing
        }
    }
    _loadSrc(index) {
        const currentIndex = index || 0;
        const sources = [...this.input.source];
        const src = sources[currentIndex];
        let nextIndex;
        if (src && sources.length > currentIndex + 1) {
            nextIndex = currentIndex + 1;
        }
        this.player
            .load(src.src)
            .then(() => {
            this._addTextTracks();
            this.state.isLoaded = true;
            this.state.failed = false;
        })
            .catch((err) => {
            if (err.code === 7000) {
                // Load interrupted by another load, just return
                return;
            }
            else if (err.code === 11) {
                // Retry, player is not loaded yet
                setTimeout(() => this._loadSrc(currentIndex), 0);
            }
            if (nextIndex) {
                setTimeout(() => this._loadSrc(nextIndex), 0);
            }
            else {
                this.handleError(err);
            }
        });
    }
    _attach() {
        var _a;
        const { Report, CurrentTime, TotalTime, MuteButton, FullscreenButton, TextSelection, } = (0, elements_1.getElements)(this);
        // eslint-disable-next-line no-undef,new-cap
        this.ui = new this.shaka.ui.Overlay(this.player, this.containerEl, this.video);
        if ((_a = document === null || document === void 0 ? void 0 : document.documentElement) === null || _a === void 0 ? void 0 : _a.lang) {
            this.ui
                .getControls()
                .getLocalization()
                .changeLocale([document.documentElement.lang]);
        }
        // eslint-disable-next-line no-undef,new-cap
        this.shaka.ui.Controls.registerElement("report", new Report.Factory());
        // eslint-disable-next-line no-undef,new-cap
        this.shaka.ui.Controls.registerElement("current_time", new CurrentTime.Factory());
        // eslint-disable-next-line no-undef,new-cap
        this.shaka.ui.Controls.registerElement("total_time", new TotalTime.Factory());
        // eslint-disable-next-line no-undef,new-cap
        this.shaka.ui.Controls.registerElement("mute_popover", new MuteButton.Factory());
        // eslint-disable-next-line no-undef,new-cap
        this.shaka.ui.Controls.registerElement("fullscreen_button", new FullscreenButton.Factory());
        // eslint-disable-next-line no-undef,new-cap
        this.shaka.ui.Controls.registerElement("captions", new TextSelection.Factory());
        this.ui.configure({
            addBigPlayButton: true,
            controlPanelElements: [],
            addSeekBar: false,
        });
        // Replace play icon
        if (this.el) {
            const playIcon = this.getComponent("play-icon").el.cloneNode(true);
            const playButton = this.el.querySelector(".shaka-play-button");
            playButton.removeAttribute("icon");
            playButton.appendChild(playIcon);
            const shakaSpinner = this.el.querySelector(".shaka-spinner");
            if (shakaSpinner) {
                setTimeout(() => {
                    shakaSpinner.hidden = true;
                }, this.input.spinnerTimeout || DEFAULT_SPINNER_TIMEOUT);
            }
        }
    }
    handleSuccess() {
        // eslint-disable-next-line no-undef,new-cap
        this.shaka.polyfill.installAll();
        // eslint-disable-next-line no-undef,new-cap
        this.player = new this.shaka.Player(this.video);
        this.player.configure(this.input.shakaConfig || {});
        this._attach();
        this._loadSrc();
    }
    onMount() {
        this.root = this.getEl("root");
        this.video = this.root.querySelector("video");
        this.containerEl = this.root.querySelector(".video-player__container");
        this.video.volume = this.input.volume || 1;
        this.video.muted = this.input.muted !== false;
        this.subscribeTo(this.video)
            .on("playing", this.handlePlaying.bind(this))
            .on("pause", this.handlePause.bind(this))
            .on("volumechange", this.handleVolumeChange.bind(this));
        eventList.forEach((eventName) => {
            this.subscribeTo(this.video).on(eventName, (e) => this.emit(eventName, e));
        });
        this._loadVideo();
    }
    onDestroy() {
        if (this.ui) {
            this.ui.destroy();
        }
    }
    _loadVideo() {
        this.state.failed = false;
        this.state.isLoaded = false;
        (0, shaka_player_1.load)()
            .then((shaka) => {
            this.shaka = shaka.default || shaka;
            window.shaka = this.shaka; // Set global object for some components to access
            this.handleSuccess();
        })
            .catch((e) => {
            console.log(e);
            this.handleError(e);
        });
    }
}
module.exports = Video;
