import { Controller } from '@hotwired/stimulus';

/*
* The following line makes this controller "lazy": it won't be downloaded until needed
* See https://github.com/symfony/stimulus-bridge#lazy-controllers
*/
/* stimulusFetch: 'lazy' */
export default class extends Controller {
    H264_CODECS = ['h264', 'h.264', 'x264']
    H265_CODECS = ['h265', 'h.265', 'x265', 'hevc']

    languages = []
    providers = []
    qualities = []
    seasons = []

    activeFilter = {
        "resolution": "",
        "codec": "",
        "language": "",
        "provider": "",
        "quality": "",
    }

    static outlets = ['movie-results', 'tv-results', 'tv-episode-list']
    static targets = ['resolution', 'codec', 'language', 'provider', 'season', 'quality', 'selectAll', 'downloadSelected']
    static values = {
        'imdbId': String,
        'media-type': String,
        'episodes': Array,
        'reverseMappedQualities': Object,
    }

    async connect() {
        if (this.mediaTypeValue === "tvshows") {
            this.activeFilter['season'] = 1;
        }
        await this.filter();
    }

    // Event is fired from movies/tvshows controllers to populate this data
    async loadOptions({detail: { options }}) {
        await options.forEach((option) => {
            this.addLanguages(option, option.dataset);
            this.addProviders(option, option.dataset);
            this.addQualities(option, option.dataset);
        })
        await this.filter();
    }

    addLanguages(option, props) {
        const languages = Object.assign([], JSON.parse(props['languages']));
        languages.forEach((language) => {
            if (!this.languages.includes(language)) {
                this.languages.push(language);
            }
        });

        const preferred = this.languageTarget.dataset.preferred;
        if (preferred) {
            this.languageTarget.innerHTML = '<option value="'+preferred+'" selected>'+preferred+'</option>';
            this.languageTarget.innerHTML += '<option value="">n/a</option>';
        } else {
            this.languageTarget.innerHTML = '<option value="">n/a</option>';
        }

        this.languageTarget.innerHTML += this.languages.sort()
            .map((language) => {
                const preferred = this.languageTarget.dataset.preferred;
                if (preferred === language) {
                    return;
                }
                return '<option value="'+language+'">'+language+'</option>';
            })
            .join();
    }

    addProviders(option, props) {
        if (!this.providers.includes(props['provider'])) {
            this.providers.push(props['provider']);
        }

        const preferred = this.providerTarget.dataset.preferred;
        if (preferred) {
            this.providerTarget.innerHTML = '<option value="'+preferred+'" selected>'+preferred+'</option>';
            this.providerTarget.innerHTML += '<option value="">n/a</option>';
        } else {
            this.providerTarget.innerHTML = '<option value="">n/a</option>';
        }

        this.providerTarget.innerHTML += this.providers.sort()
            .map((provider) => {
                const preferred = this.languageTarget.dataset.preferred;
                if (preferred === provider) {
                    return;
                }
                return '<option value="' + provider + '">' + provider + '</option>'
            })
            .join();

    }

    addQualities(option, props) {
        if (!this.qualities.includes(props['quality'])) {
            if (props['quality'].toLowerCase() in this.reverseMappedQualitiesValue) {
                this.qualities.push(props['quality']);
            }
        }

        const preferred = this.qualityTarget.dataset.preferred;
        if (preferred) {
            this.qualityTarget.innerHTML = '<option value="'+preferred+'" selected>'+preferred+'</option>';
            this.qualityTarget.innerHTML += '<option value="">n/a</option>';
        } else {
            this.qualityTarget.innerHTML = '<option value="">n/a</option>';
        }

        this.qualityTarget.innerHTML += this.qualities.sort()
            .map((quality) => {
                const preferred = this.qualityTarget.dataset.preferred;
                if (preferred === quality) {
                    return;
                }
                return '<option value="' + quality + '">' + quality + '</option>'
            })
            .join();
    }

    async filter() {
        const downloadSeasonSpan = document.querySelector("#downloadSeasonModal");
        const currentSeason = this.activeFilter['season'];

        let results = [];
        this.activeFilter = {
            "resolution": this.resolutionTarget.value,
            "codec": this.codecTarget.value,
            "language": this.languageTarget.value,
            "provider": this.providerTarget.value,
            "quality": this.qualityTarget.value,
        }

        if ("movies" === this.mediaTypeValue) {
            results = this.movieResultsOutlets;
            await results.forEach((list) => list.filter(this.activeFilter));

        } else if ("tvshows" === this.mediaTypeValue) {
            results = this.tvResultsOutlets;
            this.activeFilter.season = this.seasonTarget.value;
            downloadSeasonSpan.innerText = this.activeFilter.season;
            await results.forEach((list) => list.filter(this.activeFilter, currentSeason, this.seasonTarget.value));
        }
    }

    setSeason(event) {
        this.tvEpisodeListOutlet.setSeason(event.target.value);
    }

    uncheckSelectAllBtn() {
        this.selectAllTarget.checked = false;
    }

    downloadSeason() {
        fetch(`/api/download/season/${this.imdbIdValue}/${this.activeFilter['season']}`, {
            headers: {
                'Content-Type': 'application/json'
            }
        })
    }

    selectAllEpisodes() {
        this.tvResultsOutlets.forEach((episode) => {
            if (episode.isActive()) {
                episode.selectEpisodeForDownload()
            }
        });
    }

    downloadSelectedEpisodes() {
        this.tvResultsOutlets.forEach(episode => {
            if (episode.isActive() && episode.isSelected()) {
                episode.download();
            }
        });
        this.selectAllTarget.checked = false;
    }
}
