import React, {Component} from 'react';
import PropTypes from 'prop-types';
import { Map } from 'immutable';
import Panel from './panel';
import {TiPlus, TiDelete} from 'react-icons/ti';
import {FaPencilAlt, FaTrash, FaEye, FaArrowRight, FaAngleRight, FaAngleDoubleUp, FaAngleDown, FaOtter} from 'react-icons/fa';
import {
  FormTextInput,
  FormNumberInput,
  FormSubmitButton,
  FormSlider,
  CancelButton
} from '../style/export';

import {
  MODE_IDLE, MODE_2D_ZOOM_IN, MODE_2D_ZOOM_OUT, MODE_2D_PAN, MODE_3D_VIEW, MODE_3D_FIRST_PERSON,
  MODE_WAITING_DRAWING_LINE, MODE_DRAWING_LINE, MODE_DRAWING_HOLE, MODE_DRAWING_ITEM, MODE_DRAGGING_LINE,
  MODE_DRAGGING_VERTEX, MODE_DRAGGING_ITEM, MODE_DRAGGING_HOLE, MODE_FITTING_IMAGE, MODE_UPLOADING_IMAGE,
  MODE_ROTATING_ITEM
} from '../../constants';
import * as SharedStyle from '../../shared-style';
import { MdFileUpload, MdArrowForward, MdImage } from 'react-icons/md';
import { browserUpload } from '../../utils/browser';
import { Project, Item } from '../../class/export';


const VISIBILITY_MODE = {
  MODE_IDLE, MODE_2D_ZOOM_IN, MODE_2D_ZOOM_OUT, MODE_2D_PAN,
  MODE_3D_VIEW, MODE_3D_FIRST_PERSON,
  MODE_WAITING_DRAWING_LINE, MODE_DRAWING_LINE, MODE_DRAWING_HOLE, MODE_DRAWING_ITEM,
  MODE_DRAGGING_LINE, MODE_DRAGGING_VERTEX, MODE_DRAGGING_ITEM, MODE_DRAGGING_HOLE,
  MODE_ROTATING_ITEM, MODE_UPLOADING_IMAGE, MODE_FITTING_IMAGE
};

const tableSearchStyle = {width: '100%', marginTop: '0.8em'};
const searchIconStyle = {fontSize: '1.5em'};


const styleEditButton = {
  cursor: 'pointer',
  marginLeft: '5px',
  border: '0px',
  background: 'none',
  color: SharedStyle.COLORS.white,
  fontSize: '14px',
  outline: '0px'
};

const tableLayerStyle = {
  width: '100%',
  cursor: 'pointer',
  overflowY: 'auto',
  maxHeight: '20em',
  padding: '0 1em',
  marginLeft: '1px'
};
const chooseCamera = {
  width: '72%',
  padding: 3,
  borderRadius: 3,
  cursor: 'pointer'
}
const iconColStyle = {width: '2em', color: "white"};
const styleHoverColor = {color: SharedStyle.SECONDARY_COLOR.main};
const styleEditButtonHover = {...styleEditButton, ...styleHoverColor};
const styleAddLabel = {fontSize: '10px', marginLeft: '5px'};
const styleEyeVisible = {fontSize: '1.25em'};
const styleEyeHidden = {...styleEyeVisible, color: '#a5a1a1'};
const firstTdStyle = {width: '6em'};
const newLayerLableStyle = {margin: '0.5em 0', fontSize: '1.3em', cursor: 'pointer', textAlign: 'center'};
const newLayerLableHoverStyle = {...newLayerLableStyle, ...styleHoverColor};
const layerInputTableStyle = {width: '100%', borderSpacing: '2px 0', padding: '5px 15px'};
const inputTableButtonStyle = {float: 'right', marginTop: '0.5em', borderSpacing: '0'};
// Merge a `source` object to a `target` recursively
const merge = (target, source) => {
  // Iterate through `source` properties and if an `Object` set property to merge of `target` and `source` properties 

  for (let key of Object.keys(source)) {
    if (source[key] instanceof Object && target && source) Object.assign(source[key], merge(target[key], source[key]))
  }

  // Join `target` and modified `source`
  Object.assign(target || {}, source)
  return target
}


export default class PanelLayers extends Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      headHovered: false,
      layerAddUIVisible: false,
      editingLayer: new Map(),
      openLayers: {},
      layerList: [],
      selectedItemId: ""
    };
  }

  // shouldComponentUpdate(nextProps, nextState) {
  //   if(
  //     this.props.state.scene.layers.size !== nextProps.state.scene.layers.size ||
  //     nextState.layerAddUIVisible != this.state.layerAddUIVisible ||
  //     this.state.editingLayer.hashCode() !== nextState.editingLayer.hashCode() ||
  //     this.props.state.sceneHistory.hashCode() !== nextProps.state.sceneHistory.hashCode()
  //   ) return true;

  //   return false;
  // }

  addLayer(e) {
    e.stopPropagation();    
    if (!this.state.layerAddUIVisible) {
      this.context.sceneActions.addLayer('', 0);
      this.setState({layerAddUIVisible: false});
    }else this.setState({layerAddUIVisible: !this.state.layerAddUIVisible});

  }

  resetLayerMod(e) {
    e.stopPropagation();
    this.setState({layerAddUIVisible: false, editingLayer: new Map()});
  }

  updateLayer(e, layerData) {
    e.stopPropagation();
    let {id, name, opacity, altitude, order} = layerData.toJS();

    altitude = parseInt(altitude);

    this.context.sceneActions.setLayerProperties(id, {name, opacity, altitude, order});
    this.setState({layerAddUIVisible: false, editingLayer: new Map()});
  }

  delLayer(e, layerID) {
    e.stopPropagation();
    this.context.sceneActions.removeLayer(layerID);
    this.setState({layerAddUIVisible: false, editingLayer: new Map()});
  }

  delItem(e, layerId, element){
    e.stopPropagation();
    let {areaActions, linesActions, itemsActions} = this.context

    switch (element ? element.prototype : 'none') {
      case 'areas':
        areaActions.delectArea(layerId, element.id);
        break;
      case 'lines':
        linesActions.delectLine(layerId, element.id);
        break;
      case 'items':
        itemsActions.delectItem(layerId, element.id);
        break;
    }

  }

  loadFloorPlanFromFile(event){
    let {projectActions} = this.context
    let {state} = this.props

    console.log("project : ", this.context)
    event.stopPropagation();
    browserUpload().then((data) => {

      data = JSON.parse(data)
      console.log("floor plan file : success : ", data)
      let newLayer = {}
      if(Object.keys(data.layers).length>0){
        Object.keys(data.layers).map((key, i)=>{
          console.log("layer : ", data.layers[key])
          if(i == 0){
            newLayer = data.layers[key]
          }else{
            newLayer = merge(newLayer, data.layers[key])
          }          
        })
      }else{
        return {}
      }

      // projectActions.loadFloorPlan(JSON.parse(data));
      newLayer.name = state.get("floor")   
      newLayer.id = `nl-${Date.now()}`   
      state = Project.unselectAll( state ).updatedState
      let saveData = state.get('scene').toJS()
      saveData.layers[newLayer.id] = newLayer
      console.log("inner plan file : success : ", saveData)
      projectActions.loadFloorPlan(saveData)

    });
  }

  createNewProject(){
    console.log("create new project")
  }

  selectClick(layerID, e){
     this.context.sceneActions.selectLayer(layerID);
  }

  selectItem(layerId, element){
    let {projectActions, areaActions, linesActions, holesActions, itemsActions} = this.context

    console.log("select item : ", element, element.get("prototype"))

    if (element && element.selected) return;

    this.setState({selectedItemId: element.id})

    switch (element ? element.prototype : 'none') {
      case 'areas':
        areaActions.selectArea(layerId, element.id);
        break;

      case 'lines':
        linesActions.selectLine(layerId, element.id);
        break;

      case 'holes':
        holesActions.selectHole(layerId, element.id);
        break;

      case 'items':
        itemsActions.selectItem(layerId, element.id);
        break;

      case 'none':
        projectActions.unselectAll();
        this.setState({selectedItemId: ""})
        break;
    }
  }

  swapVisibilityItem(layerID, layer, element, e){
    e.stopPropagation()
    let visibleItems = layer.visibleItems
    if(!visibleItems[element.id])visibleItems[element.id] = true
      else visibleItems[element.id] = false
    if( typeof visibleItems != Map){
      let newMap = new Map()
      Object.keys(visibleItems).map(key=>{
        newMap[key] = visibleItems[key]
      })
      visibleItems = newMap
    } 
    this.context.sceneActions.setLayerProperties(layerID, {visibleItems})
  };



  render() {
    if (!VISIBILITY_MODE[this.props.state.mode]) return null;
    let {projectActions, translator} = this.context
    let scene = this.props.state.get("scene");
    let isLastLayer = scene.layers.size === 1;
    let {openLayers} = this.state
    let layerList = scene.layers.entrySeq()
    let itemList = []

    return (
      <Panel name={this.context.translator.t('Layers')}>
        <table style={tableLayerStyle}>
          <thead>
            <tr>
              <th></th>
              <th></th>
              <th>{this.context.translator.t('Name')}</th>
              <th colSpan='2'></th>
            </tr>
          </thead>
            {
              layerList.map(([layerID, layer]) => {
                // let selectClick = e => { }
                let configureClick = e => this.setState({editingLayer: layer, layerAddUIVisible: true})
                let openLayerItems = e =>{
                  if(!openLayers[layerID])openLayers[layerID]= true 
                  else openLayers[layerID] = false
                  console.log("open alyers : ", openLayers)
                  this.setState({openLayers})
                }
                let swapVisibility = e => {
                  // console.log("swap visibility")
                  e.stopPropagation();
                  this.context.sceneActions.setLayerProperties(layerID, {visible: !layer.visible})
                };                
                let isCurrentLayer = layerID === scene.selectedLayer;
                return (<tbody key={layerID}><tr
                    style={!isCurrentLayer ? null : styleHoverColor}
                  >
                    <td style={iconColStyle}>
                      {                       
                          <FaEye
                            onClick={swapVisibility}
                            style={!layer.visible ? styleEyeHidden : styleEyeVisible}
                          />
                      }
                    </td>
                    <td>
                         {openLayers[layerID]?<FaAngleDown onClick={openLayerItems}/>:<FaAngleRight onClick={openLayerItems}/>  } 
                    </td>
                    <td  onClick={this.selectClick.bind(this, layerID)}>
                      {layer.name} 
                    </td>
                    <td style={iconColStyle}>
                      <FaPencilAlt
                        onClick={configureClick}
                        style={!isCurrentLayer ? styleEditButton : styleEditButtonHover}
                        title={this.context.translator.t('Configure layer')}
                      />
                    </td>
                    <td style={iconColStyle}>
                      {
                        !isLastLayer?
                          <FaTrash
                            onClick={ e => this.delLayer(e, layerID) }
                            style={!isCurrentLayer ? styleEditButton : styleEditButtonHover}
                            title={this.context.translator.t('Delete layer')}
                          />
                          : <FaTrash
                          onClick={ e => confirm(translator.t('Would you want to start a new Project?')) ? projectActions.newProject() : null }
                          style={!isCurrentLayer ? styleEditButton : styleEditButtonHover}
                          title={this.context.translator.t('Delete layer')}
                        />
                      }
                    </td>
                  </tr>
                  {(openLayers[layerID])? layer.items.entrySeq().map(([id,item])=>{return <tr key={id}
                   style={(isCurrentLayer && (item.id==this.state.selectedItemId)) ? styleHoverColor : null}
                  >
                  <td>
                         &nbsp;
                  </td>
                  <td style={iconColStyle} onClick={this.swapVisibilityItem.bind(this, layerID, layer, item)}>
                      {                       
                          <FaEye
                            onClick={this.swapVisibilityItem.bind(this, layerID, layer, item)}
                            style={!layer.visibleItems[item.id] ? styleEyeVisible:styleEyeHidden}
                          />
                      }
                    </td>
                   
                    <td  onClick={this.selectItem.bind(this, layerID, item)}>
                      {item.name} 
                    </td>
                    <td style={iconColStyle}>
                     &nbsp;
                    </td>
                    <td style={iconColStyle}>
                      {
                          <FaTrash
                            onClick={ e => this.delItem(e, layerID, item) }
                            style={(isCurrentLayer && (item.id==this.state.selectedItemId)) ?  styleEditButtonHover:styleEditButton}
                            title={this.context.translator.t('Delete')}
                          />
                        
                      }
                    </td>
                  </tr>}):null}

                  {(openLayers[layerID])? layer.lines.entrySeq().map(([id,item])=>{return <tr key={id}
                   style={(isCurrentLayer && (item.id==this.state.selectedItemId)) ? styleHoverColor : null}
                  >
                  <td>
                         &nbsp;
                  </td>
                  <td style={iconColStyle} onClick={this.swapVisibilityItem.bind(this, layerID, layer, item)}>
                      {                       
                          <FaEye
                            onClick={this.swapVisibilityItem.bind(this, layerID, layer, item)}
                            style={!layer.visibleItems[item.id] ? styleEyeVisible:styleEyeHidden}
                          />
                      }
                    </td>                   
                    <td  onClick={this.selectItem.bind(this, layerID, item)}>
                      {item.name} 
                    </td>
                    <td style={iconColStyle}>
                     &nbsp;
                    </td>
                    <td style={iconColStyle}>
                      {
                          <FaTrash
                            onClick={ e => this.delItem(e, layerID, item) }
                            style={(isCurrentLayer && (item.id==this.state.selectedItemId)) ?  styleEditButtonHover:styleEditButton}
                            title={this.context.translator.t('Delete')}
                          />
                        
                      }
                    </td>
                  </tr>}):null}

                  {(openLayers[layerID])? layer.areas.entrySeq().map(([id,item])=>{return <tr key={id}
                   style={(isCurrentLayer && (item.id==this.state.selectedItemId)) ? styleHoverColor : null}
                  >
                  <td>
                         &nbsp;
                  </td>
                  <td style={iconColStyle} onClick={this.swapVisibilityItem.bind(this, layerID, layer, item)}>
                      {                       
                          <FaEye
                            onClick={this.swapVisibilityItem.bind(this, layerID, layer, item)}
                            style={!layer.visibleItems[item.id] ? styleEyeVisible:styleEyeHidden}
                          />
                      }
                    </td>
                   
                    <td  onClick={this.selectItem.bind(this, layerID, item)}>
                      {item.name} 
                    </td>
                    <td style={iconColStyle}>
                     &nbsp;
                    </td>
                    <td style={iconColStyle}>
                      {
                          <FaTrash
                            onClick={ e => this.delItem(e, layerID, item) }
                            style={(isCurrentLayer && (item.id==this.state.selectedItemId)) ?  styleEditButtonHover:styleEditButton}
                            title={this.context.translator.t('Delete')}
                          />                        
                      }
                    </td>
                  </tr>}):null}
                  </tbody>)
              })
            }
        </table>    
        {
          this.state.layerAddUIVisible && this.state.editingLayer ?
            <table style={layerInputTableStyle}>
              <tbody>            
                <tr>
                  <td style={firstTdStyle}>{this.context.translator.t('opacity')}:</td>
                  <td>
                    <FormSlider
                      min={0}
                      max={100}
                      value={Math.round(this.state.editingLayer.get('opacity') * 100)}
                      onChange={e => this.setState({editingLayer: this.state.editingLayer.merge({opacity: (e.target.value / 100)})})}
                    />
                  </td>
                </tr>               
                <tr>
                  <td colSpan="2">
                    <table style={inputTableButtonStyle}>
                      <tbody>
                        <tr>
                          <td><CancelButton size="small" onClick={ e => {
                            this.resetLayerMod(e);
                          } }>{this.context.translator.t('Reset')}</CancelButton></td>
                          <td><FormSubmitButton size="small" onClick={ e => {
                            this.updateLayer(e, this.state.editingLayer);
                          } }>{this.context.translator.t('Save')}</FormSubmitButton></td>
                        </tr>
                      </tbody>
                    </table>
                  </td>
                </tr>
              </tbody>
            </table>
            : null
        }
          <table style={tableSearchStyle}>            
            <thead>
              <tr>
                <td></td>
                <td style={{fontSize: 14, color: 'lightgreen', paddingBottom: 12}}>Upload</td>
                <td></td>
              </tr>
            </thead>
            <tbody>          
              <tr>
                <td style={{width: '15%', textAlign: 'center'}}><MdFileUpload style={searchIconStyle}/></td>
                <td><button style={chooseCamera} onClick={this.loadFloorPlanFromFile.bind(this)}> Load Data</button></td>
                <td></td>
              </tr>          
            </tbody>
          </table>
      </Panel>
    )
  }

}

PanelLayers.propTypes = {
  state: PropTypes.object.isRequired,
};

PanelLayers.contextTypes = {
  sceneActions: PropTypes.object.isRequired,
  translator: PropTypes.object.isRequired,
  projectActions: PropTypes.object.isRequired,
  itemsActions: PropTypes.object.isRequired,
  holesActions: PropTypes.object.isRequired,
  areaActions: PropTypes.object.isRequired
};
