/*
 * -------------------------------------------------------------------------
 * This file is part of the MindStudio project.
 * Copyright (c) 2025 Huawei Technologies Co.,Ltd.
 *
 * MindStudio is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 *          http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 * -------------------------------------------------------------------------
 */

import { observer } from 'mobx-react';
import { Session } from '../entity/session';
import { useRef, useState } from 'react';
import { CustomButton } from './base/StyledButton';
import { handleTimeMakerAction } from '../utils/TimeMakerUtils';
import * as React from 'react';
import styled from '@emotion/styled';
import { useWatchResize } from '../utils/useWatchDomResize';
import type { TFunction } from 'i18next';
import { useTranslation } from 'react-i18next';
import { ReactComponent as AntdPlaceFlagButtonSvg } from '../assets/images/timeline/ic_place_flag.svg';
import { FlagIcon } from '@insight/lib/icon';
import { addRangeFlag, deleteRangeFlag, linearScaleFactory, transformTimeToLeft } from './TimelineMarker';
import { runInAction } from 'mobx';
import { getTimestamp } from '../utils/humanReadable';
import type { SvgType } from './base/rc-table/types';
import { adaptDpr } from '@insight/lib/utils';

const PlaceFlagButtonSvg = AntdPlaceFlagButtonSvg as SvgType;

export const TimeMakerButton = observer(({ session }: { session: Session }): JSX.Element | null => {
    const { t } = useTranslation();
    const [isSuspend, updateIsSuspend] = useState(false);
    const [timelineMarkerModal, setTimelineMarkerModal] = useState<{ destroy: () => void } | undefined>(undefined);
    const onToolTipVisibleChange = (open: boolean): void => {
        updateIsSuspend(open);
    };
    const timeMakerProps = { session, onToolTipVisibleChange };

    React.useEffect(() => {
        timelineMarkerModal?.destroy();
        updateIsSuspend(false);
    }, [session.timelineMaker.refreshTrigger]);

    return <CustomButton data-testid={'tool-marker'} icon={FlagIcon as any} tooltip={t('timelineMarker:markerList')}
        isSuspend={ isSuspend } onClick={ (): void => { setTimelineMarkerModal(handleTimeMakerAction(timeMakerProps)); }}/>;
});

const CanvasContainer = styled.div`
    width: 100%;
`;

const rangeButtonCanvasId = 'rangeButtonCanvas';

interface RangeMarkerButtonProps {
    session: Session;
    timelineHeight: number;
}

export const RangeMarkerButtonCanvas = observer(({ session, timelineHeight }: RangeMarkerButtonProps): JSX.Element => {
    const { t } = useTranslation();
    const range = useRef<[ number, number ]>([0, 0]);
    const canvas = React.useRef<HTMLCanvasElement>(null);
    const { domainStart, domainEnd } = session.domainRange;
    const [width, ref] = useWatchResize<HTMLDivElement>('width');
    React.useEffect(() => {
        if (!canvas.current) {
            return () => {};
        }
        const singleClickListener = (e: MouseEvent): void => handleSingleClick(e, session, range, domainStart, domainEnd);
        if (session.name !== t('Realtime Monitor')) {
            addEventListener('click', singleClickListener);
        }
        drawPlaceRangeButton(session, canvas.current, [domainStart, domainEnd], t);
        range.current = [0, canvas.current.clientWidth];
        return () => {
            removeEventListener('click', singleClickListener);
        };
    }, [width, domainStart, domainEnd, session.timelineMaker.refreshTrigger, session.selectedRange]);

    React.useEffect(() => {
        const ctx = canvas.current?.getContext('2d');
        if (!canvas.current || !ctx) {
            return;
        }
        ctx.clearRect(0, 0, canvas.current.width, canvas.current.height);
    }, [session.sliceSelection.active]);

    return <CanvasContainer ref={ref}>
        <canvas
            id={ 'rangeButtonCanvas' }
            ref={canvas}
            width={ width }
            height={ timelineHeight }
            style={{ width, height: timelineHeight, position: 'absolute', top: 0, left: 0 }}/>
        <PlaceFlagButtonSvg style={{ display: 'none' }}/>
    </CanvasContainer>;
});

const drawPlaceRangeButton = (session: Session, current: HTMLCanvasElement, domain: number[], t: TFunction): void => {
    const ctx = current.getContext('2d');
    const selectedRange = session.selectedRange;
    if (!ctx || session.name === t('Realtime Monitor')) {
        return;
    }
    let buttonSvg: SVGSVGElement | undefined;
    document.querySelectorAll('svg').forEach(svgItem => {
        if (svgItem.id === 'ic_place_flag') { buttonSvg = svgItem; }
    });
    const { canvasWidth } = adaptDpr(current, ctx);
    ctx.clearRect(0, 0, current.width, current.height);
    if (buttonSvg === undefined || selectedRange === undefined) { return; }
    const rangeEndTimeStamp = selectedRange[0] > selectedRange[1] ? selectedRange[0] : selectedRange[1];
    const buttonWith = 18;
    const beginX = transformTimeToLeft(domain[0], domain[1], rangeEndTimeStamp, canvasWidth) - buttonWith;
    buttonSvg.style.fill = session.timelineMaker.oldMarkedRange === undefined ? '#5291FF' : '#5BA854';
    const buttonSvgString = new XMLSerializer().serializeToString(buttonSvg);
    const buttonSvgData = `data:image/svg+xml;base64,${btoa(buttonSvgString)}`;
    const buttonImage: HTMLImageElement = new Image();
    buttonImage.src = buttonSvgData;
    buttonImage.onload = (): void => {
        const buttonMarginTop = 10;
        ctx.drawImage(buttonImage, beginX, buttonMarginTop);
    };
};

const handleSingleClick = (e: MouseEvent, session: Session, range: React.MutableRefObject<[number, number]>, domainStart: number, domainEnd: number): void => {
    const rangeButtonCanvas = document.elementsFromPoint(e.clientX, e.clientY).find(t => t.id === rangeButtonCanvasId);
    if (!rangeButtonCanvas || session.selectedRange === undefined) {
        return;
    }
    const xScale = linearScaleFactory([domainStart, domainEnd], range.current);
    const buttonWith = 20;
    const rangeStartTimestamp = session.selectedRange[0] < session.selectedRange[1] ? session.selectedRange[0] : session.selectedRange[1];
    const rangeStartTimeDisplay = getTimestamp(rangeStartTimestamp, { precision: session.isNsMode ? 'ns' : 'ms' });
    const rangeEndTimestamp = session.selectedRange[0] > session.selectedRange[1] ? session.selectedRange[0] : session.selectedRange[1];
    const rangeEndOffset = Math.floor(xScale(rangeEndTimestamp));
    if (e.offsetX > rangeEndOffset || e.offsetX < rangeEndOffset - buttonWith) {
        return;
    }
    runInAction(() => {
        if (session.timelineMaker.oldMarkedRange === undefined) {
            session.timelineMaker.oldMarkedRange = session.selectedRange;
            addRangeFlag(session, rangeStartTimestamp, rangeStartTimeDisplay, rangeEndTimestamp);
        } else {
            session.timelineMaker.oldMarkedRange = undefined;
            deleteRangeFlag(session, rangeStartTimestamp, rangeEndTimestamp);
        }
    });
};