import React from 'react';
import ReactDOM from 'react-dom';

import { BaseGame } from '../base_game';
import { Hierarchy } from './hierarchy';
import { DebugFlagButtons, DebugFlagsType } from './debug_flag_buttons';
import { IS_DEBUG } from '../environment';
import { Entity } from '../entity';
import { Container } from 'pixi.js';
import { TextEntity } from '../text_entity';
import { Debug } from '../debug';

type ReactWrapperProps = {
  game: BaseGame<{}>;
  debugFlags: DebugFlagsType;
};

type ReactWrapperState = {
  selected: Entity | Container | null;
  moused: Entity | Container | null;
};

export class GameReactWrapper extends React.Component<ReactWrapperProps, ReactWrapperState> {
  mounted = false;

  constructor(props: ReactWrapperProps) {
    super(props);

    this.state = {
      selected: this.props.game.stage,
      moused: null,
    };

    setInterval(() => this.monitorHierarchyUpdates(), 500);
  }

  componentDidMount() {
    this.mounted = true;
  }

  componentWillUnmount() {
    console.error("This should never happen!!!! very bad?!?");
  }

  monitorHierarchyUpdates = () => {
    if (this.mounted) {
      this.forceUpdate();
    }
  };

  setSelected = (obj: Entity | Container) => {
    this.setState({
      selected: obj,
    });
  };

  setMoused = (obj: Entity | Container | null) => {
    this.setState({
      moused: obj,
    });
  };


  renderSelected = () => {
    const target = this.state.moused || this.state.selected;

    if (target === null) { return null; }

    if (target instanceof Container) {
      return (
        <div style={{ fontWeight: 600, fontFamily: 'arial', paddingTop: '8px', paddingBottom: '8px', fontSize: '18px' }}>Stage</div>
      );
    }

    let active = true;
    if (target instanceof Entity) {
      active = target.activeModes.includes(this.props.game.state.mode);
    }

    return (
      <div>
        <div style={{ fontWeight: 600, fontFamily: 'arial', paddingTop: '8px', paddingBottom: '8px', fontSize: '18px' }}>{target.name}</div>
        <div>
          x: {target.x}, y: {target.y}
        </div>
        <div>
          {active ? "Active" : "Inactive"}
        </div>
        <div>
          xAbs: {target.positionAbsolute().x}, yAbs: {target.positionAbsolute().y}
        </div>
        <div>
          width: {target.width}, height: {target.height}
        </div>
        <div>
          visible: {target.visible ? "true" : "false"}
        </div>
        <div>
          scaleX: {target.scale.x.toFixed(2)} scaleY: {target.scale.y.toFixed(2)}
        </div>
        {
          target instanceof TextEntity
            ? <div>text: {target.html}</div>
            : <div></div>
        }
      </div>
    );
  };

  renderHierarchy() {
    return (<div>
      <Hierarchy
        selectedEntity={this.state.selected}
        setMoused={this.setMoused}
        setSelected={this.setSelected}
        root={this.props.game.stage}
        gameState={this.props.game.state}
      />

      <Hierarchy
        selectedEntity={this.state.selected}
        setMoused={this.setMoused}
        setSelected={this.setSelected}
        root={this.props.game.fixedCameraStage}
        gameState={this.props.game.state}
      />
    </div>)
  }

  render() {
    return (
      <div style={{
        display: "flex",
        flexDirection: "row",
        borderLeft: IS_DEBUG ? "1px solid lightgray" : 0,
        marginLeft: '16px',
        paddingLeft: '8px',
      }}>
        <div style={{
          overflow: "auto",
          height: "90vh",
          fontFamily: 'arial',
          fontSize: '14px',
        }}>
          {this.props.game && this.props.game.stage && IS_DEBUG &&
            <div style={{ paddingLeft: '8px', }}>
              <div style={{ fontFamily: "arial", marginBottom: '8px', fontSize: '14px', width: '300px', padding: '8px' }}>
                Note: This debugging panel is only shown in development, or production with ?debug=true.
              </div>
              <div style={{ fontWeight: 600, fontFamily: 'arial', paddingBottom: '8px', fontSize: '18px' }}>Debug Options</div>
              <DebugFlagButtons flags={this.props.debugFlags} />

              <div>
                Draw Count: {Debug.GetDrawCount()}
              </div>
              {this.renderSelected()}

              <div style={{ fontWeight: 600, fontFamily: 'arial', paddingTop: '8px', paddingBottom: '8px', fontSize: '18px' }}>Debug Hierarchy</div>
              {this.renderHierarchy()}
            </div>
          }
        </div>
      </div>
    );
  }
}

export const CreateGame = (game: BaseGame<any, any, any>, debugFlags: DebugFlagsType) => {
  ReactDOM.render(
    <React.StrictMode>
      <GameReactWrapper
        game={game}
        debugFlags={debugFlags}
      />
    </React.StrictMode>,
    document.getElementById('root')
  );

  ReactDOM.render(
    <React.StrictMode>
      <Log />
    </React.StrictMode>,
    document.getElementById('log')
  );
}

export const originalConsoleLog = console.log;
const allLogs: any[][] = [];

// console.log = (...data: any[]) => {
//   allLogs.push(data);
// };

export const Log: React.FC<{}> = (props: {}) => {
  const [logs, setLogs] = React.useState<any[][]>([]);

  React.useEffect(() => {
    const interval = setInterval(() => {
      setLogs(allLogs.slice());
    }, 400);

    return () => clearInterval(interval);
  }, []);

  return (
    <div>
      {
        logs.map(logItems => {
          return (
            <div>
              {
                logItems.map(log => <span>{JSON.stringify(log)}</span>)
              }
            </div>
          );
        })
      }
    </div>
  )
}