import { PlatformLocation } from "@angular/common";
import { Component, Input, OnInit } from "@angular/core";
import { DomSanitizer } from "@angular/platform-browser";
import { Subject } from "rxjs";
import { debounceTime, distinctUntilChanged } from "rxjs/operators";

import { AuthService } from "../auth/auth.service";
import { FilterType, IFilter, IIssueCategory, IMovieRequests, IPagenator, IRadarrProfile, IRadarrRootFolder, OrderType } from "../interfaces";
import { NotificationService, RadarrService, RequestService } from "../services";

@Component({
    selector: "movie-requests",
    templateUrl: "./movierequests.component.html",
})
export class MovieRequestsComponent implements OnInit {
    public movieRequests: IMovieRequests[];
    public defaultPoster: string;

    public searchChanged: Subject<string> = new Subject<string>();
    public searchText: string;

    public isAdmin: boolean; // Also PowerUser

    public radarrProfiles: IRadarrProfile[];
    public radarrRootFolders: IRadarrRootFolder[];

    @Input() public issueCategories: IIssueCategory[];
    @Input() public issuesEnabled: boolean;
    public issuesBarVisible = false;
    public issueRequest: IMovieRequests;
    public issueProviderId: string;
    public issueCategorySelected: IIssueCategory;

    public filterDisplay: boolean;
    public filter: IFilter;
    public filterType = FilterType;

    public orderType: OrderType = OrderType.RequestedDateDesc;
    public OrderType = OrderType;

    public totalMovies: number = 100;
    private currentlyLoaded: number;
    private amountToLoad: number;

    constructor(
        private requestService: RequestService,
        private auth: AuthService,
        private notificationService: NotificationService,
        private radarrService: RadarrService,
        private sanitizer: DomSanitizer,
        private readonly platformLocation: PlatformLocation) {
        this.searchChanged.pipe(
            debounceTime(600), // Wait Xms after the last event before emitting last event
            distinctUntilChanged(), // only emit if value is different from previous value
        ).subscribe(x => {
            this.searchText = x as string;
            if (this.searchText === "") {
                this.resetSearch();
                return;
            }
            this.requestService.searchMovieRequests(this.searchText)
                .subscribe(m => {
                    this.setOverrides(m);
                    this.movieRequests = m;
                });
        });
        this.defaultPoster = "../../../images/default_movie_poster.png";
        const base = this.platformLocation.getBaseHrefFromDOM();
        if (base) {
            this.defaultPoster = "../../.." + base + "/images/default_movie_poster.png";
        }
    }

    public ngOnInit() {
        this.amountToLoad = 10;
        this.currentlyLoaded = 10;
        this.filter = {
            availabilityFilter: FilterType.None,
            statusFilter: FilterType.None,
        };
        this.loadInit();
        this.isAdmin = this.auth.hasRole("admin") || this.auth.hasRole("poweruser");
    }

    public paginate(event: IPagenator) {
        const skipAmount = event.first;
        this.loadRequests(this.amountToLoad, skipAmount);
    }

    public search(text: any) {
        this.searchChanged.next(text.target.value);
    }

    public removeRequest(request: IMovieRequests) {
        this.requestService.removeMovieRequest(request);
        this.removeRequestFromUi(request);
        this.loadRequests(this.amountToLoad, this.currentlyLoaded = 0);
    }

    public changeAvailability(request: IMovieRequests, available: boolean) {
        request.available = available;

        if (available) {
            this.requestService.markMovieAvailable({ id: request.id }).subscribe(x => {
                if (x.result) {
                    this.notificationService.success(
                        `${request.title} Is now available`);
                } else {
                    this.notificationService.warning("Request Available", x.message ? x.message : x.errorMessage);
                    request.approved = false;
                }
            });
        } else {
            this.requestService.markMovieUnavailable({ id: request.id }).subscribe(x => {
                if (x.result) {
                    this.notificationService.success(
                        `${request.title} Is now unavailable`);
                } else {
                    this.notificationService.warning("Request Available", x.message ? x.message : x.errorMessage);
                    request.approved = false;
                }
            });
        }
    }

    public approve(request: IMovieRequests) {
        request.approved = true;
        this.approveRequest(request);
    }

    public deny(request: IMovieRequests) {
        request.denied = true;
        this.denyRequest(request);
    }

    public selectRootFolder(searchResult: IMovieRequests, rootFolderSelected: IRadarrRootFolder, event: any) {
        event.preventDefault();
        searchResult.rootPathOverride = rootFolderSelected.id;
        this.setOverride(searchResult);
        this.updateRequest(searchResult);
    }

    public selectQualityProfile(searchResult: IMovieRequests, profileSelected: IRadarrProfile, event: any) {
        event.preventDefault();
        searchResult.qualityOverride = profileSelected.id;
        this.setOverride(searchResult);
        this.updateRequest(searchResult);
    }

    public reportIssue(catId: IIssueCategory, req: IMovieRequests) {
        this.issueRequest = req;
        this.issueCategorySelected = catId;
        this.issuesBarVisible = true;
        this.issueProviderId = req.theMovieDbId.toString();
    }

    public ignore(event: any): void {
        event.preventDefault();
    }

    public clearFilter(el: any) {
        el = el.toElement || el.relatedTarget || el.target || el.srcElement;

        el = el.parentElement;
        el = el.querySelectorAll("INPUT");
        for (el of el) {
            el.checked = false;
            el.parentElement.classList.remove("active");
        }

        this.filterDisplay = false;
        this.filter.availabilityFilter = FilterType.None;
        this.filter.statusFilter = FilterType.None;

        this.resetSearch();
    }

    public filterAvailability(filter: FilterType, el: any) {
        this.filterActiveStyle(el);
        this.filter.availabilityFilter = filter;
        this.loadInit();
    }

    public filterStatus(filter: FilterType, el: any) {
        this.filterActiveStyle(el);
        this.filter.statusFilter = filter;
        this.loadInit();
    }

    public setOrder(value: OrderType, el: any) {
        el = el.toElement || el.relatedTarget || el.target || el.srcElement;

        const parent = el.parentElement;
        const previousFilter = parent.querySelector(".active");

        previousFilter.className = "";
        el.className = "active";

        this.orderType = value;

        this.loadInit();
    }

    public subscribe(request: IMovieRequests) {
        request.subscribed = true;
        this.requestService.subscribeToMovie(request.id)
            .subscribe(x => {
                this.notificationService.success("Subscribed To Movie!");
            });
    }

    public unSubscribe(request: IMovieRequests) {
        request.subscribed = false;
        this.requestService.unSubscribeToMovie(request.id)
            .subscribe(x => {
                this.notificationService.success("Unsubscribed Movie!");
            });
    }

    private filterActiveStyle(el: any) {
        el = el.toElement || el.relatedTarget || el.target || el.srcElement;

        el = el.parentElement; //gets radio div
        el = el.parentElement; //gets form group div
        el = el.parentElement; //gets status filter div
        el = el.querySelectorAll("INPUT");
        for (el of el) {
            if (el.checked) {
                if (!el.parentElement.classList.contains("active")) {
                    el.parentElement.className += " active";
                }
            } else {
                el.parentElement.classList.remove("active");
            }
        }
    }

    private loadRequests(amountToLoad: number, currentlyLoaded: number) {
        this.requestService.getMovieRequests(amountToLoad, currentlyLoaded, this.orderType, this.filter)
            .subscribe(x => {
                this.setOverrides(x.collection);
                if (!this.movieRequests) {
                    this.movieRequests = [];
                }
                this.movieRequests = x.collection;
                this.totalMovies = x.total;
                this.currentlyLoaded = currentlyLoaded + amountToLoad;
            });
    }

    private updateRequest(request: IMovieRequests) {
        this.requestService.updateMovieRequest(request)
            .subscribe(x => {
                this.setOverride(x);
                request = x;
            });
    }

    private approveRequest(request: IMovieRequests) {
        this.requestService.approveMovie({ id: request.id })
            .subscribe(x => {
                request.approved = true;
                if (x.result) {
                    this.notificationService.success(
                        `Request for ${request.title} has been approved successfully`);
                } else {
                    this.notificationService.warning("Request Approved", x.message ? x.message : x.errorMessage);
                    request.approved = false;
                }
            });
    }

    private denyRequest(request: IMovieRequests) {
        this.requestService.denyMovie({ id: request.id })
            .subscribe(x => {
                if (x.result) {
                    this.notificationService.success(
                        `Request for ${request.title} has been denied successfully`);
                } else {
                    this.notificationService.warning("Request Denied", x.message ? x.message : x.errorMessage);
                    request.denied = false;
                }
            });
    }

    private loadInit() {
        this.requestService.getMovieRequests(this.amountToLoad, 0, this.orderType, this.filter)
            .subscribe(x => {
                this.movieRequests = x.collection;
                this.totalMovies = x.total;

                this.movieRequests.forEach((req) => {
                    this.setBackground(req);
                    this.setPoster(req);
                });
                if (this.isAdmin) {
                    this.radarrService.getQualityProfilesFromSettings().subscribe(c => {
                        this.radarrProfiles = c;
                        this.movieRequests.forEach((req) => this.setQualityOverrides(req));
                    });
                    this.radarrService.getRootFoldersFromSettings().subscribe(c => {
                        this.radarrRootFolders = c;
                        this.movieRequests.forEach((req) => this.setRootFolderOverrides(req));
                    });
                }
            });
    }

    private resetSearch() {
        this.currentlyLoaded = 5;
        this.loadInit();
    }

    private removeRequestFromUi(key: IMovieRequests) {
        const index = this.movieRequests.indexOf(key, 0);
        if (index > -1) {
            this.movieRequests.splice(index, 1);
        }
    }

    private setOverrides(requests: IMovieRequests[]): void {
        requests.forEach((req) => {
            this.setOverride(req);
        });
    }

    private setQualityOverrides(req: IMovieRequests): void {
        if (this.radarrProfiles) {
            const profile = this.radarrProfiles.filter((p) => {
                return p.id === req.qualityOverride;
            });
            if (profile.length > 0) {
                req.qualityOverrideTitle = profile[0].name;
            }
        }
    }
    private setRootFolderOverrides(req: IMovieRequests): void {
        if (this.radarrRootFolders) {
            const path = this.radarrRootFolders.filter((folder) => {
                return folder.id === req.rootPathOverride;
            });
            if (path.length > 0) {
                req.rootPathOverrideTitle = path[0].path;
            }
        }
    }

    private setOverride(req: IMovieRequests): void {
        this.setPoster(req);
        this.setBackground(req);
        this.setQualityOverrides(req);
        this.setRootFolderOverrides(req);
    }

    private setPoster(req: IMovieRequests): void {
        if (req.posterPath === null) {
            req.posterPath = this.defaultPoster;
        } else {
            req.posterPath = "https://image.tmdb.org/t/p/w300/" + req.posterPath;
        }
    }

    private setBackground(req: IMovieRequests): void {
        req.backgroundPath = this.sanitizer.bypassSecurityTrustStyle
            ("url(" + "https://image.tmdb.org/t/p/w1280" + req.background + ")");
    }
}
