export default class DownloadOptionTr extends HTMLTableRowElement {
    H264_CODECS = {
        'h264': 'h264',
        'h.264': 'h264',
        'x264': 'h264',
    }
    H265_CODECS = {
        'h265': 'h265',
        'h.265': 'h265',
        'x265': 'h265',
        'hevc': 'h265',
    }

    #downloadBtnEl;
    #selectEpisodeInputEl;

    url;
    size;
    quality;
    resolution;
    codec;
    seeders;
    provider;
    languages;
    mediaType;
    season;
    episode;
    filename;
    imdbId;
    episodeId;
    mediaTitle;

    constructor() {
        super();
        this.url = this.getAttribute('url');
        this.size = this.getAttribute('size');
        this.quality = this.getAttribute('quality');
        this.resolution = this.getAttribute('resolution');
        this.codec = this.getAttribute('codec');
        this.seeders = this.getAttribute('seeders');
        this.provider = this.getAttribute('provider');
        this.filename = this.getAttribute('filename');
        this.imdbId = this.getAttribute('imdb-id');
        this.languages = JSON.parse(this.getAttribute('languages'));
        this.mediaType = this.getAttribute('media-type');
        this.mediaTitle = this.getAttribute('media-title');
        this.season = this.getAttribute('season') ?? null;
        this.episode = this.getAttribute('episode') ?? null;
        this.episodeId = this.getAttribute('episode-id') ?? null;
        this.#downloadBtnEl = this.querySelector('.download-btn');
        this.#selectEpisodeInputEl = this.querySelector('input[type="checkbox"]');

        this.#downloadBtnEl.addEventListener('click', () => this.download());
    }
    get isSelected() {
        return this.#selectEpisodeInputEl.checked;
    }

    set isSelected(value) {
        this.#selectEpisodeInputEl.checked = value;
    }

    filter({ detail: { activeFilter } }) {
        const optionHeader = document.querySelector(`[data-option-id="${this.dataset['localId']}"]`)

        let include = true;
        this.classList.add('r-tablerow');
        this.classList.remove('hidden');
        optionHeader.classList.add('r-tablerow');
        optionHeader.classList.remove('hidden');

        this.querySelector('input[type="checkbox"]').checked = false;

        if (!this.#validateResolutions(activeFilter.resolution)) {
            include = false;
        }

        if (!this.#validateCodecs(activeFilter.codec)) {
            include = false;
        }

        if (!this.#validateLanguages(activeFilter.language)) {
            include = false;
        }

        if (!this.#validateQualities(activeFilter.quality)) {
            include = false;
        }

        if (!this.#validateProviders(activeFilter.provider)) {
            include = false;
        }

        if (false === include) {
            this.classList.remove('r-tablerow');
            this.classList.add('hidden');
            optionHeader.classList.remove('r-tablerow');
            optionHeader.classList.add('hidden');
        }

        return include;
    }

    download() {
        const preferencesForm = document.querySelector('[name="user_media_preferences_form"]');
        const preferences = {
            resolution: preferencesForm.querySelector('[id="user_media_preferences_form_resolution"]').value,
            codec: preferencesForm.querySelector('[id="user_media_preferences_form_codec"]').value,
            language: preferencesForm.querySelector('[id="user_media_preferences_form_language"]').value,
            quality: preferencesForm.querySelector('[id="user_media_preferences_form_quality"]').value,
            provider: preferencesForm.querySelector('[id="user_media_preferences_form_provider"]').value,
        }
        fetch('/api/download', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Accept': 'application/json',
            },
            body: JSON.stringify({
                mediaType: this.mediaType,
                imdbId: this.imdbId,
                season: this.season,
                episode: this.episode,
                filter: preferences,
            })
        })
            .then(res => res.json())
            .then(json => {
                console.log(json)
            })
    }

    #validateResolutions(selectedOptions) {
        return this.#validateIntersection(selectedOptions, this.resolution.trim().split(','));
    }

    #validateCodecs(selectedOptions) {
        if (this.#validateIntersection(selectedOptions, Object.keys(this.H264_CODECS))) {
            return this.#validateIntersection(
                selectedOptions,
                [...this.codec.trim().split(','), '', 'n/a']
            );
        }
        if (this.#validateIntersection(selectedOptions, Object.keys(this.H265_CODECS))) {
            return this.#validateIntersection(
                selectedOptions,
                [...this.codec.trim().split(','), '', 'n/a']
            );
        }
        return false;
    }

    #validateQualities(selectedOptions) {
        return this.#validateIntersection(selectedOptions, this.quality.trim().split(','));
    }

    #validateProviders(selectedOptions) {
        return this.#validateIntersection(selectedOptions, this.provider.trim().split(','));
    }

    #validateLanguages(selectedOptions) {
        return this.#validateIntersection(selectedOptions, this.languages);
    }

    #validateIntersection(selectedOptions, localOptions) {
        if (selectedOptions === null || selectedOptions === undefined) {
            return true;
        }

        if (typeof selectedOptions === 'string' || selectedOptions instanceof String) {
            selectedOptions = [selectedOptions];
        }

        if (selectedOptions.length === 0 ||
            (selectedOptions.length === 1 && selectedOptions[0] === "") ||
            (selectedOptions.length === 1 && selectedOptions[0] === "n/a")
        ) {
            return true;
        }

        return this.#doesIntersect(localOptions, selectedOptions);
    }

    #doesIntersect(a, b) {
        if (a.length === 0 || b.length === 0) {
            return false;
        }
        return this.#intersect(a, b).length > 0;
    }

    #intersect(a, b) {
        return a.filter(Set.prototype.has, new Set(b));
    }
}
