import * as ko from "knockout";
import * as Constants from "../../../../../src/constants";
import template from "./subscription-list-dropdown.html";
import { Component, RuntimeComponent, OnMounted, Param, OnDestroyed } from "@paperbits/common/ko/decorators";
import { Router } from "@paperbits/common/routing";
import { SubscriptionCustom } from "../../../../../src/models/subscriptionCustom";
import { SearchQuery } from "../../../../../src/contracts/searchQuery";
import { RouteHelper } from "../../../../../src/routing/routeHelper";
import { AnalyticsServiceCustom } from "../../../../../src/services/analyticsServiceCustom";


@RuntimeComponent({
    selector: "subscription-list-dropdown-runtime"
})
@Component({
    selector: "subscription-list-dropdown-runtime",
    template: template
})
export class SubscriptionListDropdown {
    public readonly subscriptions: ko.ObservableArray<SubscriptionCustom>;
    public readonly working: ko.Observable<boolean>;
    public readonly selectedId: ko.Observable<string>;
    public readonly selectedSubscription: ko.Observable<SubscriptionCustom>;
    public readonly selectedSubscriptionName: ko.Observable<string>;
    public readonly pattern: ko.Observable<string>;
    public readonly page: ko.Observable<number>;
    public readonly hasPager: ko.Computed<boolean>;
    public readonly hasPrevPage: ko.Observable<boolean>;
    public readonly hasNextPage: ko.Observable<boolean>;
    public readonly expanded: ko.Observable<boolean>;
    public readonly selection: ko.Computed<string>;

    constructor(
        private readonly router: Router,
        private readonly routeHelper: RouteHelper,
        private readonly analyticsServiceCustom: AnalyticsServiceCustom
    ) {
        this.detailsPageUrl = ko.observable();
        this.allowSelection = ko.observable(false);
        this.working = ko.observable();
        this.selectedId = ko.observable();
        this.pattern = ko.observable();
        this.page = ko.observable(1);
        this.hasPrevPage = ko.observable();
        this.hasNextPage = ko.observable();
        this.hasPager = ko.computed(() => this.hasPrevPage() || this.hasNextPage());
        this.subscriptions = ko.observableArray();
        this.selectedSubscription = ko.observable();
        this.selectedSubscriptionName = ko.observable();
        this.expanded = ko.observable(false);
        this.selection = ko.computed(() => {
            const subscription = ko.unwrap(this.selectedSubscription);
            return subscription ? subscription.name : "Select subscription";
        });
    }

    @Param()
    public readonly allowSelection: ko.Observable<boolean>;

    @Param()
    public readonly detailsPageUrl: ko.Observable<string>;

    @OnMounted()
    public async initialize(): Promise<void> {
        await this.resetSearch();

        this.pattern
            .extend({ rateLimit: { timeout: Constants.defaultInputDelayMs, method: "notifyWhenChangesStop" } })
            .subscribe(this.resetSearch);

        this.router.addRouteChangeListener(this.onRouteChange);
    }

    /**
     * Initiates searching Products.
     */
    public async resetSearch(): Promise<void> {
        this.page(1);
        this.loadPageOfProducts();
    }

    private async onRouteChange(): Promise<void> {
        const productName = this.routeHelper.getProductName();

        if (productName !== this.selectedSubscriptionName()) {
            await this.resetSearch();
            return;
        }

        await this.resetSearch();
        this.handleSubscriptionListDropdownSelect(this);
    }

    /**
     * Loads page of Products.
     */
    public async loadPageOfProducts(): Promise<void> {
        try {
            this.working(true);

            const pageNumber = this.page() - 1;

            const query: SearchQuery = {
                pattern: this.pattern(),
                skip: pageNumber * Constants.defaultPageSize,
                take: Constants.defaultPageSize
            };

            const itemsPage = await this.analyticsServiceCustom.getSubscriptionsForUser(query);
            console.log(itemsPage);

            this.subscriptions(itemsPage.value);
            this.hasPrevPage(pageNumber > 0);
            this.hasNextPage(!!itemsPage.nextLink);

            const productName = this.routeHelper.getProductName();

            this.selectedSubscription(productName
                ? itemsPage.value.find(item => item.name == productName)
                : undefined);

            this.handleSubscriptionListDropdownSelect(this);
        }
        catch (error) {
            throw new Error(`Unable to load APIs. Error: ${error.message}`);
        }
        finally {
            this.working(false);
        }
    }

    public prevPage(): void {
        this.page(this.page() - 1);
        this.loadPageOfProducts();
    }

    public nextPage(): void {
        this.page(this.page() + 1);
        this.loadPageOfProducts();
    }

    @Param()
    public handleSubscriptionListDropdownSelect(data: SubscriptionListDropdown
        // , event
    ): void {
        alert('Dropdown select handler in child.');
        console.log(data);
    }

    public toggle(): void {
        this.expanded(!this.expanded());
    }

    public getProductUrl(product: SubscriptionCustom): string {
        return this.routeHelper.getProductReferenceUrl(product.name, this.detailsPageUrl());
    }
    
    @OnDestroyed()
    public dispose(): void {
        this.router.removeRouteChangeListener(this.onRouteChange);
    }
}