/**
 * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
 * SPDX-License-Identifier: MIT
 */

import { useState } from 'react';

import {
  usePlayground,
  FlowNodeEntity,
  FixedLayoutPluginContext,
  useClientContext,
  delay,
} from '@flowgram.ai/fixed-layout-editor';
import { Button } from '@douyinfe/semi-ui';

const styleElement = document.createElement('style');
const RUNNING_COLOR = 'rgb(78, 64, 229)';
const RUNNING_INTERVAL = 1000;

function getRunningNodes(targetNode?: FlowNodeEntity | undefined, addChildren?: boolean): string[] {
  const result: string[] = [];
  if (targetNode) {
    result.push(targetNode.id);
    if (addChildren) {
      result.push(...targetNode.allChildren.map((n) => n.id));
    }
    if (targetNode.parent) {
      result.push(targetNode.parent.id);
    }
    if (targetNode.pre) {
      result.push(...getRunningNodes(targetNode.pre, true));
    }
    if (targetNode.parent) {
      if (targetNode.parent.pre) {
        result.push(...getRunningNodes(targetNode.parent.pre, true));
      }
    }
  }
  return result;
}

function clear() {
  styleElement.innerText = '';
}

function runningNode(ctx: FixedLayoutPluginContext, nodeId: string) {
  const nodes = getRunningNodes(ctx.document.getNode(nodeId), true);
  if (nodes.length === 0) {
    styleElement.innerText = '';
  } else {
    const content = nodes
      .map(
        (n) => `
      path[data-line-id$="${n}"] {
        animation: flowingDash 0.5s linear infinite;
        stroke-dasharray: 8, 5;
        stroke: ${RUNNING_COLOR} !important;
      }
      marker[data-line-id$="${n}"] path {
        fill: ${RUNNING_COLOR} !important;
      }
      [data-node-id$="${n}"] {
        border: 1px dashed ${RUNNING_COLOR} !important;
        border-radius: 8px;
      }
      [data-label-id$="${n}"] {
        color: ${RUNNING_COLOR} !important;
      }
    `
      )
      .join('\n');
    styleElement.innerText = `
   @keyframes flowingDash {
    to {
      stroke-dashoffset: -13;
    }
  }
  ${content}
  `;
  }
  if (!styleElement.parentNode) {
    document.body.appendChild(styleElement);
  }
}

/**
 * Run the simulation and highlight the lines
 */
export function Run() {
  const [isRunning, setRunning] = useState(false);
  const ctx = useClientContext();
  const playground = usePlayground();
  const onRun = async () => {
    setRunning(true);
    playground.config.readonly = true;
    const nodes = ctx.document.root.blocks.slice();
    while (nodes.length > 0) {
      const currentNode = nodes.shift();
      runningNode(ctx, currentNode!.id);
      await delay(RUNNING_INTERVAL);
    }

    playground.config.readonly = false;
    clear();
    setRunning(false);
  };
  return (
    <Button onClick={onRun} loading={isRunning}>
      Run
    </Button>
  );
}
