import { DomUtils } from "@devexpress/utils/lib/utils/dom";
import { Task } from "../../Model/Entities/Task";
import { TooltipSettings } from "../Settings/InitSettings/TooltipSettings";
import { ElementTextHelperCultureInfo } from "../Utils/ElementTextHelperCultureInfo";

export class TaskEditTooltip {
    public static CLASSNAMES = {
        TASK_EDIT_PROGRESS_STATUS: "dx-gantt-task-edit-tooltip",
        TASK_EDIT_TOOLTIP_DEFAULT: "dx-gantt-task-edit-tooltip-default",
        TASK_EDIT_TASK_TITLE: "dx-gantt-task-title",
        TASK_EDIT_PROGRESS_STATUS_TIME: "dx-gantt-status-time",
        TASK_EDIT_TOOLTIP_ARROW_BEFORE: "dx-gantt-task-edit-tooltip-before",
        TASK_EDIT_TOOLTIP_ARROW_AFTER: "dx-gantt-task-edit-tooltip-after"

    }
    private parentElement: HTMLElement;
    private _baseElement: HTMLElement;
    private defaultTooltip: HTMLElement;
    private timerId: number;
    private cultureInfo: ElementTextHelperCultureInfo;
    public tooltipSettings: TooltipSettings;

    constructor(parentElement: HTMLElement, tooltipSettings: TooltipSettings, cultureInfo: ElementTextHelperCultureInfo) {
        this.parentElement = parentElement;
        this.cultureInfo = cultureInfo;
        this.tooltipSettings = tooltipSettings;
    }

    private get baseElement(): HTMLElement {
        if(!this._baseElement)
            this.createTooltipContainer();
        return this._baseElement;
    }

    private get headerHeight(): number {
        return this.tooltipSettings.getHeaderHeight;
    }

    private get taskTooltipContentTemplate(): (container: HTMLElement, model: any, ...args) => any {
        return this.tooltipSettings.getTaskTooltipContentTemplate;
    }

    private get taskProgressTooltipContentTemplate(): (container: HTMLElement, model: any, ...args) => void {
        return this.tooltipSettings.getTaskProgressTooltipContentTemplate;
    }

    private get taskTimeTooltipContentTemplate(): (container: HTMLElement, model: any, ...args) => void {
        return this.tooltipSettings.getTaskTimeTooltipContentTemplate;
    }

    private destroyTemplate(container: HTMLElement): void {
        this.tooltipSettings.destroyTemplate(container);
    }

    private formatDate(date: Date): string {
        return this.tooltipSettings.formatDate(date);
    }

    private createTooltipContainer() {
        this._baseElement = document.createElement("DIV");
        this._baseElement.className = TaskEditTooltip.CLASSNAMES.TASK_EDIT_PROGRESS_STATUS;
        this.parentElement.appendChild(this._baseElement);
    }

    private setDefaultTooltip(task: Task): void {
        this.defaultTooltip = document.createElement("DIV");
        this.defaultTooltip.className = TaskEditTooltip.CLASSNAMES.TASK_EDIT_TOOLTIP_DEFAULT;
        const titleWrapper = document.createElement("DIV");
        titleWrapper.className = TaskEditTooltip.CLASSNAMES.TASK_EDIT_TASK_TITLE;
        const title = document.createElement("SPAN");
        titleWrapper.appendChild(title);
        this.defaultTooltip.appendChild(titleWrapper);
        title.innerText = task.title;
        this.defaultTooltip.appendChild(this.getTimeContent(task.start, task.end));

        if(!isNaN(task.progress)) {
            const progressElement = document.createElement("DIV");
            progressElement.className = TaskEditTooltip.CLASSNAMES.TASK_EDIT_PROGRESS_STATUS_TIME;
            const progressTitle = document.createElement("SPAN");
            const progressValue = document.createElement("SPAN");
            progressElement.appendChild(progressTitle);
            progressElement.appendChild(progressValue);
            this.defaultTooltip.appendChild(progressElement);
            progressTitle.innerText = (this.cultureInfo.progress ? this.cultureInfo.progress : "Progress") + ": ";
            progressValue.innerText = task.progress + "%";
        }
        this.baseElement.appendChild(this.defaultTooltip);
    }
    private setDefaultProgressTooltip(progress: number) {
        this.defaultTooltip = document.createElement("DIV");
        this.defaultTooltip.className = TaskEditTooltip.CLASSNAMES.TASK_EDIT_TOOLTIP_DEFAULT;
        this.defaultTooltip.innerText = progress + "%";
        this.baseElement.appendChild(this.defaultTooltip);
    }
    private setDefaultTimeTooltip(start: Date, end: Date) {
        this.defaultTooltip = document.createElement("DIV");
        this.defaultTooltip.className = TaskEditTooltip.CLASSNAMES.TASK_EDIT_TOOLTIP_DEFAULT;
        this.defaultTooltip.appendChild(this.getTimeContent(start, end));
        this.baseElement.appendChild(this.defaultTooltip);
    }

    public showInfo(task: Task, posX: number, delay: number = 0): void {
        const tooltipTemplateFunction = this.taskTooltipContentTemplate;
        this.destroyTemplate(this.baseElement);

        if(tooltipTemplateFunction)
            tooltipTemplateFunction(this.baseElement, task,
                () => { this.showTooltip(posX, false, delay); });
        else {
            this.setDefaultTooltip(task);
            this.showTooltip(posX, false, delay);
        }
    }
    public showProgress(progress: number, posX: number): void {
        const tooltipTemplateFunction = this.taskProgressTooltipContentTemplate;
        this.destroyTemplate(this.baseElement);
        if(tooltipTemplateFunction)
            tooltipTemplateFunction(this.baseElement, { progress: progress },
                () => { this.showTooltip(posX); });
        else {
            this.setDefaultProgressTooltip(progress);
            this.show(posX);
        }
    }
    public showTime(start: Date, end: Date, posX: number): void {
        const tooltipTemplateFunction = this.taskTimeTooltipContentTemplate;
        this.destroyTemplate(this.baseElement);
        if(tooltipTemplateFunction)
            tooltipTemplateFunction(this.baseElement, { start: start, end: end },
                () => { this.showTooltip(posX); });
        else {
            this.setDefaultTimeTooltip(start, end);
            this.show(posX);
        }
    }

    public showTooltip(posX: number, autoHide: boolean = true, delay: number = 0): void {
        if(this.baseElement?.innerHTML) {
            const showInfoFunc = () => {
                this.show(posX, autoHide);
            };
            if(delay)
                this.timerId = setTimeout(showInfoFunc, delay);
            else
                showInfoFunc();
        }
    }

    public show(posX: number, autoHide: boolean = true): void {
        const arrowHeight = 5;
        const heightOffset = 15;
        this.defaultTooltip?.classList.remove(TaskEditTooltip.CLASSNAMES.TASK_EDIT_TOOLTIP_ARROW_AFTER);
        this.defaultTooltip?.classList.remove(TaskEditTooltip.CLASSNAMES.TASK_EDIT_TOOLTIP_ARROW_BEFORE);
        this.baseElement.style.display = "block";
        const absolutePositionY = DomUtils.getAbsolutePositionY(this.parentElement);
        const absoluteX = DomUtils.getAbsolutePositionX(this.parentElement);
        const leftPosition = posX - absoluteX - 2 * arrowHeight;
        const absoluteDistance = absolutePositionY - this.headerHeight - DomUtils.getDocumentScrollTop() - heightOffset;
        const isShowingDown = this.baseElement.clientHeight > absoluteDistance || this.baseElement.clientHeight > this.parentElement.offsetTop;
        let topPosition = -this.baseElement.clientHeight - arrowHeight;

        if(isShowingDown) {
            topPosition = this.parentElement.clientHeight + arrowHeight;
            this.defaultTooltip?.classList.add(TaskEditTooltip.CLASSNAMES.TASK_EDIT_TOOLTIP_ARROW_AFTER);
        }
        else
            this.defaultTooltip?.classList.add(TaskEditTooltip.CLASSNAMES.TASK_EDIT_TOOLTIP_ARROW_BEFORE);

        this.baseElement.style.left = leftPosition + "px";
        this.baseElement.style.top = topPosition + "px";
        if(autoHide) {
            if(this.timerId)
                clearTimeout(this.timerId);
            this.timerId = setTimeout(() => {
                this.hide();
            }, 1500);
        }
    }
    public hide(): void {
        this.baseElement.style.display = "none";
        this.destroyTemplate(this.baseElement);
        clearTimeout(this.timerId);
    }
    private getTimeContent(start: Date, end: Date): HTMLElement {
        const timeElement = document.createElement("TABLE");
        timeElement.className = TaskEditTooltip.CLASSNAMES.TASK_EDIT_PROGRESS_STATUS_TIME;
        const body = document.createElement("TBODY");
        timeElement.appendChild(body);
        const startEl = document.createElement("TR");
        const startTitle = document.createElement("TD");
        const startValue = document.createElement("TD");
        const endEl = document.createElement("TR");
        const endTitle = document.createElement("TD");
        const endValue = document.createElement("TD");

        startEl.appendChild(startTitle);
        startEl.appendChild(startValue);
        endEl.appendChild(endTitle);
        endEl.appendChild(endValue);
        body.appendChild(startEl);
        body.appendChild(endEl);

        startTitle.innerText = (this.cultureInfo.start ? this.cultureInfo.start : "Start") + ": ";
        startValue.innerText = this.formatDate(start);
        endTitle.innerText = (this.cultureInfo.end ? this.cultureInfo.end : "End") + ": ";
        endValue.innerText = this.formatDate(end);

        return timeElement;
    }
}
