import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Rnd } from 'react-rnd';
import ns from '../config/css-ns';
import { getWorkspaceBoundingBox } from '../state/selectors';

const minimapContainer = {
  width: 200,
  height: 200,
  innerPadding: 10,
};

// There is a minimum bounding box based on the viewport dimensions,
// and the bounding box is always square

/**
 * ElasticMinimap
 */
const scaledViewport = (workspaceViewport, boundingBox) => {
  const viewportAspectRatio = workspaceViewport.width / workspaceViewport.height;
  const viewportScaleFactor = workspaceViewport.width / boundingBox.width;

  const scaledViewportWidth = viewportScaleFactor * minimapContainer.width;
  const scaledViewportHeight = scaledViewportWidth / viewportAspectRatio;
  const scaledViewportX = (-workspaceViewport.x / boundingBox.width) * minimapContainer.width;
  const scaledViewportY = (-workspaceViewport.y / boundingBox.height) * minimapContainer.height;

  return {
    x: scaledViewportX,
    y: scaledViewportY,
    width: scaledViewportWidth,
    height: scaledViewportHeight,
  };
};

/**
 * ElasticMinimap
 */
const minimapToWorkspaceCoordinates = (x, y, boundingBox) => {
  const newX = -x * boundingBox.width / minimapContainer.width;
  const newY = -y * boundingBox.height / minimapContainer.height;
  return {
    x: newX,
    y: newY,
  };
};

/**
 * ElasticMinimap
 */
const windowStyle = (window, boundingBox) => {
  const windowAspectRatio = window.width / window.height;
  const windowScaleFactor = window.width / boundingBox.width;

  const scaledWindowWidth = windowScaleFactor * 100;
  const scaledWindowX = (window.x / boundingBox.width) * 100;
  const scaledWindowY = (window.y / boundingBox.height) * 100;
  const scaledWindowHeight = scaledWindowWidth / windowAspectRatio;

  return {
    top: `${scaledWindowY}%`,
    left: `${scaledWindowX}%`,
    height: `${scaledWindowHeight}%`,
    width: `${scaledWindowWidth}%`,
  };
};

/**
 * ElasticMinimap
 */
const boundingBoxStyle = (windows, boundingBox) => {
  const windowBoundingBox = getWorkspaceBoundingBox(windows);
  const windowBBAspectRatio = windowBoundingBox.width / windowBoundingBox.height;
  const windowBBScaleFactor = windowBoundingBox.width / boundingBox.width;

  const scaledWindowBBWidth = windowBBScaleFactor * 100;
  const scaledWindowBBX = (windowBoundingBox.x / boundingBox.width) * 100;
  const scaledWindowBBY = (windowBoundingBox.y / boundingBox.height) * 100;
  const scaledWindowBBHeight = scaledWindowBBWidth / windowBBAspectRatio;

  return {
    top: `${scaledWindowBBY}%`,
    left: `${scaledWindowBBX}%`,
    height: `${scaledWindowBBHeight}%`,
    width: `${scaledWindowBBWidth}%`,
  };
};

/**
 * ElasticMinimap
 */
export class ElasticMinimap extends Component {
  /**
   * render
   * @return
   */
  render() {
    const boundingBox = {
      width: 5000,
      height: 5000,
    };

    const {
      windows,
      workspaceViewport,
      setWorkspaceViewportPosition,
    } = this.props;

    const viewport = scaledViewport(
      workspaceViewport,
      boundingBox,
    );

    return (
      <div className={ns('elastic-minimap')}>
        {
          Object.values(windows).map(window => (
            <div
              key={window.id}
              className="minimap-window"
              style={windowStyle(window, boundingBox)}
            />
          ))
        }
        <div
          className="window-bounding-box"
          style={boundingBoxStyle(windows, boundingBox)}
        />
        <Rnd
          position={{ x: viewport.x, y: viewport.y }}
          size={{ width: viewport.width, height: viewport.height }}
          enableResizing={{
            top: false,
            right: false,
            bottom: false,
            left: false,
            topRight: false,
            bottomRight: false,
            bottomLeft: false,
            topLeft: false,
          }}
          onDragStart={(e, d) => null}
          onDrag={(e, d) => {
            const newPosition = minimapToWorkspaceCoordinates(d.x, d.y, boundingBox);
            setWorkspaceViewportPosition(newPosition.x, newPosition.y);
          }}
          className="minimap-viewport"
        />
      </div>
    );
  }
}

ElasticMinimap.propTypes = {
  windows: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
  setWorkspaceViewportPosition: PropTypes.func.isRequired,
  workspaceViewport: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
};