import { computed, flow, observable, runInAction, set } from "mobx";

import { request } from "../utils/request.js";
import { locationRestSeoClearAttachmentDelete } from "../wp-api/seo-clear-attachment.delete.js";
import { locationRestSeoClearProcessDelete } from "../wp-api/seo-clear-process.delete.js";
import { locationRestSeoClearThumbnailDelete } from "../wp-api/seo-clear-thumbnail.delete.js";

import type { SeoOriginalItem } from "./seoOriginalItem.js";
import type { SeoStore } from "../store/seo.js";
import type { ClassProperties } from "../utils/types.js";
import type {
    ParamsRestSeoClearAttachmentDelete,
    RequestRestSeoClearAttachmentDelete,
    ResponseRestSeoClearAttachmentDelete,
} from "../wp-api/seo-clear-attachment.delete.js";
import type {
    ParamsRestSeoClearProcessDelete,
    RequestRestSeoClearProcessDelete,
    ResponseRestSeoClearProcessDelete,
} from "../wp-api/seo-clear-process.delete.js";
import type {
    ParamsRestSeoClearThumbnailDelete,
    RequestRestSeoClearThumbnailDelete,
    ResponseRestSeoClearThumbnailDelete,
} from "../wp-api/seo-clear-thumbnail.delete.js";

type CancellablePromise<R> = ReturnType<ReturnType<typeof flow<R, any>>>;

class SeoItem {
    @observable
    public type?: "older" | "thumbnail" | "original" = "original";

    @observable
    public original?: SeoOriginalItem;

    @observable
    public id: number;

    @observable
    public processId: string;

    @observable
    public attachment: number;

    @observable
    public fromHash: string;

    @observable
    public fromUrl: string;

    @observable
    public toUrl: string;

    @observable
    public modified: string;

    @observable
    public size: string;

    @observable
    public validFullHash: string;

    @observable
    public deleteBusy = false;

    @computed public get fromUrlShort() {
        return this.urlTruncate(this.fromUrl);
    }

    @computed public get toUrlShort() {
        return this.urlTruncate(this.toUrl);
    }

    public readonly seoStore: SeoStore;

    public constructor(seoItem: Partial<ClassProperties<SeoItem>>, seoStore: SeoStore) {
        this.seoStore = seoStore;
        runInAction(() => set(this, seoItem));
    }

    private urlTruncate(url: string) {
        const { origin } = window.location;
        return url.startsWith(origin) ? url.substr(origin.length) : url;
    }

    public trash: () => CancellablePromise<boolean> = flow(function* (this: SeoOriginalItem) {
        this.deleteBusy = true;

        try {
            switch (this.type) {
                case "original":
                    yield request<
                        RequestRestSeoClearAttachmentDelete,
                        ParamsRestSeoClearAttachmentDelete,
                        ResponseRestSeoClearAttachmentDelete
                    >({
                        location: locationRestSeoClearAttachmentDelete,
                        params: {
                            id: this.attachment,
                        },
                    });
                    this.seoStore.items.splice(this.seoStore.items.indexOf(this), 1);
                    this.seoStore.count--;
                    break;
                case "thumbnail":
                    yield request<
                        RequestRestSeoClearThumbnailDelete,
                        ParamsRestSeoClearThumbnailDelete,
                        ResponseRestSeoClearThumbnailDelete
                    >({
                        location: locationRestSeoClearThumbnailDelete,
                        params: {
                            id: this.id,
                        },
                    });
                    this.original.thumbnails.splice(this.original.thumbnails.indexOf(this), 1);
                    break;
                case "older":
                    yield request<
                        RequestRestSeoClearProcessDelete,
                        ParamsRestSeoClearProcessDelete,
                        ResponseRestSeoClearProcessDelete
                    >({
                        location: locationRestSeoClearProcessDelete,
                        params: {
                            processId: this.processId,
                        },
                    });
                    this.original.olderEntries.splice(this.original.olderEntries.indexOf(this), 1);
                    break;
                default:
                    return false;
            }
            return true;
        } catch (e) {
            return false;
        } finally {
            this.deleteBusy = false;
        }
    });
}

export { SeoItem };
