import React from 'react';
import PropTypes from 'prop-types';
import {
  Mosaic, getLeaves, createBalancedTreeFromLeaves,
} from 'react-mosaic-component';
import 'react-mosaic-component/react-mosaic-component.css';
import Window from '../containers/Window';

/**
 * Represents a work area that contains any number of windows
 * @memberof Workspace
 * @private
 */
class WorkspaceMosaic extends React.Component {
  /**
   */
  constructor(props) {
    super(props);

    this.tileRenderer = this.tileRenderer.bind(this);
    this.mosaicChange = this.mosaicChange.bind(this);
    this.determineWorkspaceLayout = this.determineWorkspaceLayout.bind(this);
  }

  /**
   * Render a tile (Window) in the Mosaic.
   */
  tileRenderer(id, path) {
    const { windows } = this.props;
    const window = windows[id];
    if (!window) return null;
    return (
      <Window
        key={window.id}
        window={window}
      />
    );
  }

  /**
   * Update the redux store when the Mosaic is changed.
   */
  mosaicChange(newLayout) {
    const { updateWorkspaceMosaicLayout } = this.props;
    updateWorkspaceMosaicLayout(newLayout);
  }

  /**
   * Used to determine whether or not a "new" layout should be autogenerated.
   * If a Window is added or removed, generate that new layout and use that for
   * this render. When the Mosaic changes, that will trigger a new store update.
   */
  determineWorkspaceLayout() {
    const { windows, workspace } = this.props;
    const windowKeys = Object.keys(windows);
    const leaveKeys = getLeaves(workspace.layout);
    // Check every window is in the layout, and all layout windows are present
    // in store
    if (!windowKeys.every(e => leaveKeys.includes(e))
    || !leaveKeys.every(e => windowKeys.includes(e))) {
      const newLayout = createBalancedTreeFromLeaves(windowKeys);
      return newLayout;
    }
    return null;
  }

  /**
   */
  render() {
    const { workspace } = this.props;
    const newLayout = this.determineWorkspaceLayout();
    return (
      <Mosaic
        renderTile={this.tileRenderer}
        initialValue={newLayout || workspace.layout}
        onChange={this.mosaicChange}
        className="mirador-mosaic"
        zeroStateView={<div />}
      />
    );
  }
}


WorkspaceMosaic.propTypes = {
  updateWorkspaceMosaicLayout: PropTypes.func.isRequired,
  windows: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
  workspace: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
};

export default WorkspaceMosaic;