/*
* @Author: zhouningyi
* @Date: 2016-12-27 15:52:11
*/

import React, { Component, PropTypes } from 'react';
import _      from 'lodash';

import UiBase from './../uiBase';

import Block from './../Block';

import Gradient from './../Gradient';
import Select from './../Select';
import Toggle from './../Toggle';
import Range  from './../Range';

import zscale from 'zscale';
import dataTypes from './../../meta/dataTypes';
const binding = dataTypes.binding;

const {floor} = Math;

const defaultProps = {
  meadianRange: {
    min: 0.05, 
    max: 0.95
  }
};

export function getStyles(){
}

export default class Binding extends UiBase {
  static propTypes = {
    data:    PropTypes.any.isRequired,
    onChange: PropTypes.func.isRequired,
    onFinishChange: PropTypes.func,
  }
  constructor(props: any) {
    super(props);
    this.state = {
      data: this.props.data
    };
    this._updateDomain();
  }
  _genFunc(){
    let value = this.state.data;
    let {domain, range, type, key} = value;
    key = key.value;
    const func = zscale.generate({
      type: 'gradient',
      value: { domain, range }
    });
    return (d) => {
      return func(d[key])
    };
  }
  _updateDomain(){
    const {value} = this.state.data;
    let ds = this.props.dataSource || value.data;
    const key = value.key.value;
    const isExist = d => d[key] !== undefined && d[key] !== null;
    const defaultDomain = {min: 0, max: 1};
    if(!ds || !ds.length){
      value.domain = value.domain || defaultDomain;
    } else if(value.isLock){
      ds = ds.filter(isExist);
      ds = _.sortBy(ds, d => d[key]);
      if(!ds || !ds.length) return defaultDomain;
      const {meadianRange} = defaultProps;
      const dsLength = ds.length;
      const minIndex = floor(meadianRange.min * dsLength);
      const maxIndex = floor(meadianRange.max * dsLength);
      const min = ds[minIndex][key];
      const max = ds[maxIndex][key];
      value.domain = {
        min: Math.min(min, max), 
        max: Math.max(min, max)
      };
    }
  }
  onKeyChange = (d) => {
    _.set(this.state.data, 'value.key.value', d.key);
    this.onBindingChange();
  }
  onLockChange = (d) => {
    _.set(this.state.data, 'value.isLock', d.isLock);
    this._updateDomain();
    this.onBindingChange();
  }
  onDomainChange = (d) => {
    if(d === undefined || d === null) return;
    _.set(this.state.data, 'value.domain', d.range);
    this.onBindingChange();
  }
  onRangeChange = (d, validation, value) => {
    if(value.value) value = value.value;
    _.set(this.state.data, 'value.range', value.range || value);
    this.onBindingChange();
  }
  onBindingChange(){
    this.onChange(this.state.data.value);
  }
  render(){
    const {value} = this.state.data;
    const {heightPhi} = this.props;
    const height = this._getDefaultHeight() * heightPhi + 'px';
    const {key} = value;
    const select = {
      key: 'key',
      name: '选择字段',
      value: key.value,
      validate: {
        options: key.options
      }
    };
    
    const toggle = {
      name: '锁定',
      key: 'isLock',
      value: value.isLock,
    };

    const domain = {
      name: '取值范围',
      key: 'range',
      value: value.domain,
      disable: value.isLock
    };

    const {type} = value;
    const Tag = type === 'gradient' ? Gradient : Range;
    let range;
    if(type === 'gradient'){
      range = {
        name: '颜色映射',
        key: type,
        value: {
          domain: value.domain,
          range:  value.range
        }
      };
    } else {
      range = {
        name: '大小映射',
        key: type,
        value:  value.range
      };
    }

    return (
      <Block>
        <Select data={select} onChange={this.onKeyChange} editable={false}></Select>
        <div className="z_combound_container">
          <div className="z_combound_left">
            <Range data={domain} onChange={this.onDomainChange} editable={false}></Range>
          </div>
          <div className="z_combound_right">
            <Toggle data={toggle} onChange={this.onLockChange} editable={false}></Toggle>
          </div>
        </div>
        <Tag data={range} onChange={this.onRangeChange} editable={false}></Tag>
      </Block>
    )
  }
};

