import React from 'react';
import HeaderBar from './header-bar';
import Select from 'react-select';
import SignaturePad from 'react-signature-pad';
import SortableItemMixin from 'react-sortable-items/SortableItemMixin';
import SliderNativeBootstrap from 'react-bootstrap-native-slider';
import ReactDatePicker from 'react-datepicker';
import StarRating from './star-rating';
import xss from 'xss';
import moment from 'moment';

let FormElements = {};
let myxss = new xss.FilterXSS({
  whiteList: {
    u: [],
    br: [],
    b: [],
    i: [],
    ul: [],
    li: []
  }
});

let Header = React.createClass({
  mixins: [SortableItemMixin],
  render() {
    let headerClasses = 'dynamic-input ' + this.props.data.element + '-input';
    let classNames = 'static';
    if (this.props.data.bold) { classNames += ' bold'; }
    if (this.props.data.italic) { classNames += ' italic'; }

    return this.renderWithSortable(
      <div className="rfb-item">
        { !this.props.mutable &&
          <HeaderBar parent={this.props.parent} editModeOn={this.props.editModeOn} data={this.props.data} onDestroy={this.props._onDestroy} onEdit={this.props.onEdit} static={this.props.data.static} required={this.props.data.required} />
        }
        <h3 className={classNames}>{this.props.data.content}</h3>
      </div>
    );
  }
})


let Paragraph = React.createClass({
  mixins: [SortableItemMixin],
  render() {
    let classNames = 'static';
    if (this.props.data.bold) { classNames += ' bold'; }
    if (this.props.data.italic) { classNames += ' italic'; }

    return this.renderWithSortable(
      <div className="rfb-item">
        { !this.props.mutable &&
          <HeaderBar parent={this.props.parent} editModeOn={this.props.editModeOn} data={this.props.data} onDestroy={this.props._onDestroy} onEdit={this.props.onEdit} static={this.props.data.static} required={this.props.data.required} />
        }
        <p className={classNames} dangerouslySetInnerHTML={{__html: myxss.process(this.props.data.content) }} />
      </div>
    );
  }
})

let Label = React.createClass({
  mixins: [SortableItemMixin],
  render() {
    let classNames = 'static';
    if (this.props.data.bold) { classNames += ' bold'; }
    if (this.props.data.italic) { classNames += ' italic'; }

    return this.renderWithSortable(
      <div className="rfb-item">
        { !this.props.mutable &&
          <HeaderBar parent={this.props.parent} editModeOn={this.props.editModeOn} data={this.props.data} onDestroy={this.props._onDestroy} onEdit={this.props.onEdit} static={this.props.data.static} required={this.props.data.required} />
        }
        <label className={classNames} dangerouslySetInnerHTML={{__html: myxss.process(this.props.data.content) }} />
      </div>
    );
  }
})

let LineBreak = React.createClass({
  mixins: [SortableItemMixin],
  render() {
    return this.renderWithSortable(
      <div className="rfb-item">
        { !this.props.mutable &&
          <HeaderBar parent={this.props.parent} editModeOn={this.props.editModeOn} data={this.props.data} onDestroy={this.props._onDestroy} onEdit={this.props.onEdit} static={this.props.data.static} required={this.props.data.required} />
        }
        <hr />
      </div>
    );
  }
})

let TextInput = React.createClass({
  mixins: [SortableItemMixin],
  render() {
    let props = {};
    props.type = "text";
    props.className = "form-control";
    props.name = this.props.data.field_name;

    if (this.props.mutable) {
      props.defaultValue = this.props.defaultValue;
      props.ref = "child_ref_" + this.props.data.field_name;
    }
    return this.renderWithSortable(
      <div className="rfb-item">
        { !this.props.mutable &&
          <HeaderBar parent={this.props.parent} editModeOn={this.props.editModeOn} data={this.props.data} onDestroy={this.props._onDestroy} onEdit={this.props.onEdit} static={this.props.data.static} required={this.props.data.required} />
        }
        <div className="form-group">
          <label>
            <span dangerouslySetInnerHTML={{__html: myxss.process(this.props.data.label) }} />

            { (this.props.data.hasOwnProperty('required') && this.props.data.required === true) &&
              <span className="label-required label label-danger">Required</span>
            }
          </label>
          <input {...props} />
        </div>
      </div>
    );
  }
})

let NumberInput = React.createClass({
  mixins: [SortableItemMixin],
  render() {
    let props = {};
    props.type = "number";
    props.className = "form-control";
    props.name = this.props.data.field_name;

    if (this.props.mutable) {
      props.defaultValue = this.props.defaultValue;
      props.ref = "child_ref_" + this.props.data.field_name;
    }
    return this.renderWithSortable(
      <div className="rfb-item">
        { !this.props.mutable &&
          <HeaderBar parent={this.props.parent} editModeOn={this.props.editModeOn} data={this.props.data} onDestroy={this.props._onDestroy} onEdit={this.props.onEdit} static={this.props.data.static} required={this.props.data.required} />
        }
        <div className="form-group">
          <label>
            <span dangerouslySetInnerHTML={{__html: myxss.process(this.props.data.label) }} />

            { (this.props.data.hasOwnProperty('required') && this.props.data.required === true) &&
              <span className="label-required label label-danger">Required</span>
            }
          </label>
          <input {...props} />
        </div>
      </div>
    );
  }
})

let TextArea = React.createClass({
  mixins: [SortableItemMixin],
  render() {
    let props = {};
    props.className = "form-control";
    props.name = this.props.data.field_name;

    if (this.props.mutable) {
      props.defaultValue = this.props.defaultValue;
      props.ref = "child_ref_" + this.props.data.field_name;
    }
    return this.renderWithSortable(
      <div className="rfb-item">
        { !this.props.mutable &&
          <HeaderBar parent={this.props.parent} editModeOn={this.props.editModeOn} data={this.props.data} onDestroy={this.props._onDestroy} onEdit={this.props.onEdit} static={this.props.data.static} required={this.props.data.required} />
        }
        <div className="form-group">
          <label>
            <span dangerouslySetInnerHTML={{__html: myxss.process(this.props.data.label) }} />
            { (this.props.data.hasOwnProperty('required') && this.props.data.required === true) &&
              <span className="label-required label label-danger">Required</span>
            }
          </label>
          <textarea {...props} />
        </div>
      </div>
    );
  }
})

let DatePicker = React.createClass({
  mixins: [SortableItemMixin],

  getInitialState() {
    var value, internalValue, placeholderValue;

    // Is today defaulted?
    if(this.props.data.defaultToday) {
      placeholderValue = moment().format('MM/DD/YYYY');
    }

    value = this.props.defaultValue;
    if(this.props.defaultValue !== '' && this.props.defaultValue !== undefined) {
      // Otherwise, is there a default value?  If so, set up the internal value to a moment object.
      internalValue = moment(this.props.defaultValue);
    }    

    return {
      value: value, 
      internalValue: internalValue, 
      placeholder: 'mm/dd/yyyy',
      placeholderValue: placeholderValue
    };
  },

  handleChange(dt) {
    if(dt && dt.target) {

      var placeholder = (dt && dt.target && dt.target.value === '') ? 'mm/dd/yyyy': '';
      var formattedDate = (dt.target.value) ? moment(dt.target.value).format('YYYY-MM-DD') : '';

      this.setState({
        value: formattedDate,
        internalValue: formattedDate,
        placeholder: placeholder
      });

    } else {
      this.setState({
        value: (dt) ? dt.format('MM/DD/YYYY') : '',
        internalValue: dt,
        placeholder: placeholder
      });
    }
  },

  render() {
    let props = {};
    props.type = "date";
    props.className = "form-control";
    props.name = this.props.data.field_name;

    var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;

    if (this.props.mutable) {
      props.defaultValue = this.props.defaultValue;
      props.ref = "child_ref_" + this.props.data.field_name;
    }

    var value, internalValue;

    if(this.state.value === undefined && this.props.data.defaultToday) {
      // Is there no value already set and default should be today.  Set today's date.
      value = (this.state.placeholderValue) ? this.state.placeholderValue : moment().format('MM/DD/YYYY');
    } else {
      value = this.state.value;
    }

    if(this.state.internalValue === undefined && this.props.data.defaultToday) {
      // Is there no internal value already set and default should be today.  Set today's date.
      internalValue = moment();
    } else {
      internalValue = this.state.internalValue;
    }
    
    return this.renderWithSortable(
      <div className="rfb-item">
        { !this.props.mutable &&
          <HeaderBar parent={this.props.parent} editModeOn={this.props.editModeOn} data={this.props.data} onDestroy={this.props._onDestroy} onEdit={this.props.onEdit} static={this.props.data.static} required={this.props.data.required} />
        }
        <div className="form-group">
          <label>
            <span dangerouslySetInnerHTML={{__html: myxss.process(this.props.data.label) }} />
            { (this.props.data.hasOwnProperty('required') && this.props.data.required === true) &&
              <span className="label-required label label-danger">Required</span>
            }
          </label>
          <div>
            { this.props.data.readOnly &&
              <input type="text" 
                name={props.name}
                ref={props.ref}
                readOnly="true"
                dateFormat="MM/DD/YYYY"
                placeholder={this.state.placeholder}
                value={value}
                className="form-control" />
            }
            { iOS && !this.props.data.readOnly &&
              <input type="date"
                name={props.name}
                ref={props.ref}
                onChange={this.handleChange}
                dateFormat="MM/DD/YYYY"
                placeholder={this.state.placeholder}
                value={value}
                className = "form-control" />
            }
            { !iOS && !this.props.data.readOnly &&
              <ReactDatePicker
                name={props.name}
                ref={props.ref}
                onChange={this.handleChange}
                selected={internalValue}
                todayButton={'Today'}
                className = "form-control"
                isClearable={true}
                dateFormat="MM/DD/YYYY"
                placeholderText='mm/dd/yyyy' />
            }
          </div>
        </div>
      </div>
    );
  }
})

let Dropdown = React.createClass({
  mixins: [SortableItemMixin],
  render() {
    let props = {};
    props.className = "form-control";
    props.name = this.props.data.field_name;

    if (this.props.mutable) {
      props.defaultValue = this.props.defaultValue;
      props.ref = "child_ref_" + this.props.data.field_name;
    }
    return this.renderWithSortable(
      <div className="rfb-item">
        { !this.props.mutable &&
          <HeaderBar parent={this.props.parent} editModeOn={this.props.editModeOn} data={this.props.data} onDestroy={this.props._onDestroy} onEdit={this.props.onEdit} static={this.props.data.static} required={this.props.data.required} />
        }
        <div className="form-group">
          <label>
            <span dangerouslySetInnerHTML={{__html: myxss.process(this.props.data.label) }} />
            { (this.props.data.hasOwnProperty('required') && this.props.data.required === true) &&
              <span className="label-required label label-danger">Required</span>
            }
          </label>
          <select {...props}>
            {this.props.data.options.map(function (option) {
              let this_key = 'preview_' + option.key;
              return <option value={option.value} key={this_key}>{option.text}</option>;
            })}
          </select>
        </div>
      </div>
    );
  }
})


let Signature = React.createClass({
  mixins: [SortableItemMixin],
  componentDidMount() {
    if (this.props.defaultValue !== undefined && this.props.defaultValue.length > 0) {
      let canvas = this.refs['canvas_'+this.props.data.field_name];
      canvas.fromDataURL('data:image/png;base64,' + this.props.defaultValue);
    }
  },
  render() {
    let props = {};
    props.type = "hidden";
    props.name = this.props.data.field_name;

    if (this.props.mutable) {
      props.defaultValue = this.props.defaultValue;
      props.ref = "child_ref_" + this.props.data.field_name;
    }
    let pad_props = {};
    pad_props.clearButton = {true};
    if (this.props.mutable) {
      pad_props.defaultValue = this.props.defaultValue;
      pad_props.ref = 'canvas_'+this.props.data.field_name;
    }
    return this.renderWithSortable(
      <div className="rfb-item">
        { !this.props.mutable &&
          <HeaderBar parent={this.props.parent} editModeOn={this.props.editModeOn} data={this.props.data} onDestroy={this.props._onDestroy} onEdit={this.props.onEdit} static={this.props.data.static} required={this.props.data.required} />
        }
        <div className="form-group">
          <label>
            <span dangerouslySetInnerHTML={{__html: myxss.process(this.props.data.label) }} />
            { (this.props.data.hasOwnProperty('required') && this.props.data.required === true) &&
              <span className="label-required label label-danger">Required</span>
            }
          </label>
          <SignaturePad {...pad_props} />
          <input {...props} />
        </div>
      </div>
    );
  }
})

let Tags = React.createClass({
  mixins: [SortableItemMixin],
  getInitialState() {
    return {value: this.props.defaultValue !== undefined ? this.props.defaultValue.split(",") : []};
  },
  handleChange(e) {
    this.setState({value: e});
  },
  render() {
    let options = this.props.data.options.map( option => {
      option.label = option.text;
      return option;
    })
    let props = {};
    props.multi = true;
    props.name = this.props.data.field_name;
    props.onChange = this.handleChange;

    props.options = options;
    if (!this.props.mutable) {props.value = options[0].text} // to show a sample of what tags looks like
    if (this.props.mutable) {
      props.value = this.state.value;
      props.ref = "child_ref_" + this.props.data.field_name;
    }
    return this.renderWithSortable(
      <div className="rfb-item">
        { !this.props.mutable &&
          <HeaderBar parent={this.props.parent} editModeOn={this.props.editModeOn} data={this.props.data} onDestroy={this.props._onDestroy} onEdit={this.props.onEdit} static={this.props.data.static} required={this.props.data.required} />
        }
        <div className="form-group">
          <label>
            <span dangerouslySetInnerHTML={{__html: myxss.process(this.props.data.label) }} />
            { (this.props.data.hasOwnProperty('required') && this.props.data.required === true) &&
              <span className="label-required label label-danger">Required</span>
            }
          </label>
          <Select {...props} />
        </div>
      </div>
    );
  }
})

let Checkboxes = React.createClass({
  mixins: [SortableItemMixin],
  render() {
    let self = this;
    let classNames = 'checkbox-label';
    if (this.props.data.inline) { classNames += ' option-inline'; }

    return this.renderWithSortable(
      <div className="rfb-item">
        { !this.props.mutable &&
          <HeaderBar parent={this.props.parent} editModeOn={this.props.editModeOn} data={this.props.data} onDestroy={this.props._onDestroy} onEdit={this.props.onEdit} static={this.props.data.static} required={this.props.data.required} />
        }
        <div className="form-group">
          <label className="form-label">
            <span dangerouslySetInnerHTML={{__html: myxss.process(this.props.data.label) }} />
            { (this.props.data.hasOwnProperty('required') && this.props.data.required === true) &&
              <span className="label-required label label-danger">Required</span>
            }
          </label>
          {this.props.data.options.map(function (option) {
            let this_key = 'preview_' + option.key;
            let props = {};
            props.name = 'option_'+option.key;

            props.type = "checkbox"
            props.value = option.value;
            if (self.props.mutable) {
              props.defaultChecked = self.props.defaultValue.indexOf(option.value) > -1 ? true : false;
              props.ref = "child_ref_" + option.key;
            }
            return (
              <label className={classNames} key={this_key}>
                <input {...props} /> {option.text}
              </label>
            )
          })}
        </div>
      </div>
    );
  }
})

let RadioButtons = React.createClass({
  mixins: [SortableItemMixin],
  render() {
    let self = this;
    let classNames = 'radio-label';
    if (this.props.data.inline) { classNames += ' option-inline'; }
    console.log(this.props.data.inline);

    return this.renderWithSortable(
      <div className="rfb-item">
        { !this.props.mutable &&
          <HeaderBar parent={this.props.parent} editModeOn={this.props.editModeOn} data={this.props.data} onDestroy={this.props._onDestroy} onEdit={this.props.onEdit} static={this.props.data.static} required={this.props.data.required} />
        }
        <div className="form-group">
          <label className="form-label">
            <span dangerouslySetInnerHTML={{__html: myxss.process(this.props.data.label) }} />
            { (this.props.data.hasOwnProperty('required') && this.props.data.required === true) &&
              <span className="label-required label label-danger">Required</span>
            }
          </label>
          {this.props.data.options.map(function (option) {
            let this_key = 'preview_' + option.key;
            let props = {};
            props.name = self.props.data.field_name;

            props.type = "radio"
            props.value = option.value;
            if (self.props.mutable) {
              props.defaultChecked = (self.props.defaultValue !== undefined && self.props.defaultValue.indexOf(option.value) > -1) ? true : false;
              props.ref = "child_ref_" + option.key;
            }
            return (
              <label className={classNames} key={this_key}>
                <input {...props} /> {option.text}
              </label>
            )
          })}
        </div>
      </div>
    );
  }
})

let Rating = React.createClass({
  mixins: [SortableItemMixin],
  render() {
    let props = {};
    props.name = this.props.data.field_name;
    props.ratingAmount = 5;

    if (this.props.mutable) {
      props.rating = (this.props.defaultValue !== undefined && this.props.defaultValue.length) ? parseFloat(this.props.defaultValue, 10) : 0;
      props.editing = true;
      props.ref = "child_ref_" + this.props.data.field_name;
    }
    return this.renderWithSortable(
      <div className="rfb-item">
        { !this.props.mutable &&
          <HeaderBar parent={this.props.parent} editModeOn={this.props.editModeOn} data={this.props.data} onDestroy={this.props._onDestroy} onEdit={this.props.onEdit} static={this.props.data.static} required={this.props.data.required} />
        }
        <div className="form-group">
          <label>
            <span dangerouslySetInnerHTML={{__html: myxss.process(this.props.data.label) }} />
            { (this.props.data.hasOwnProperty('required') && this.props.data.required === true) &&
              <span className="label-required label label-danger">Required</span>
            }
          </label>
          <StarRating {...props} />
        </div>
      </div>
    );
  }
})

let HyperLink = React.createClass({
  mixins: [SortableItemMixin],
  render() {
    return this.renderWithSortable(
      <div className="rfb-item">
        { !this.props.mutable &&
          <HeaderBar parent={this.props.parent} editModeOn={this.props.editModeOn} data={this.props.data} onDestroy={this.props._onDestroy} onEdit={this.props.onEdit} static={this.props.data.static} required={this.props.data.required} />
        }
        <div className="form-group">
          <a target="_blank" href={this.props.data.href}>{this.props.data.content}</a>
        </div>
      </div>
    );
  }
})

let Download = React.createClass({
  mixins: [SortableItemMixin],
  render() {
    return this.renderWithSortable(
      <div className="rfb-item">
        { !this.props.mutable &&
          <HeaderBar parent={this.props.parent} editModeOn={this.props.editModeOn} data={this.props.data} onDestroy={this.props._onDestroy} onEdit={this.props.onEdit} static={this.props.data.static} required={this.props.data.required} />
        }
        <div className="form-group">
          <a href={this.props.download_path + '?id=' + this.props.data.file_path}>{this.props.data.content}</a>
        </div>
      </div>
    );
  }
})

let Camera = React.createClass({
  mixins: [SortableItemMixin],

  getInitialState() {
    return {img: null};
  },

  displayImage(e) {
    var self = this;
    var target = e.target;
    var file, reader;

    if(target.files && target.files.length) {
      file = target.files[0];
      reader = new FileReader();
      reader.readAsDataURL(file);

      reader.onloadend = function() {
        self.setState({
          img: reader.result
        });
      }
    }
  },

  clearImage() {
    this.setState({
      img: null
    })
  },

  render() {
    return this.renderWithSortable(
      <div className="rfb-item">
        { !this.props.mutable &&
          <HeaderBar parent={this.props.parent} editModeOn={this.props.editModeOn} data={this.props.data} onDestroy={this.props._onDestroy} onEdit={this.props.onEdit} static={this.props.data.static} required={this.props.data.required} />
        }
        <div className="form-group">
          <label>
            {this.props.data.label}
            { (this.props.data.hasOwnProperty('required') && this.props.data.required === true) &&
              <span className="label-required label label-danger">Required</span>
            }
          </label>
          <div className="image-upload-container">

            { !this.state.img &&
              <div>
                <input type="file" accept="image/*" capture="camera" className="image-upload" onChange={this.displayImage} />
                <div className="image-upload-control">
                  <div className="btn btn-default btn-school"><i className="fa fa-camera"></i> Upload Photo</div>
                  <p>Select an image from your computer or device.</p>
                </div>
              </div>
            }

            { this.state.img &&
              <div>
                <img src={ this.state.img } height="100" className="image-upload-preview" /><br />
                <div className="btn btn-school btn-image-clear" onClick={this.clearImage}>
                  <i className="fa fa-times"></i> Clear Photo
                </div>
              </div>
            }

          </div>
        </div>
      </div>
    );
  }
})

let Range = React.createClass({
  mixins: [SortableItemMixin],
  render() {
    let props = {};
    props.type = "range";
    props.name = this.props.data.field_name;
    props.list = "tickmarks_" + this.props.data.field_name;
    props.min = this.props.data.min_value;
    props.max = this.props.data.max_value;
    props.step = this.props.data.step;

    props.defaultValue = this.props.defaultValue !== undefined ? parseInt(this.props.defaultValue, 10) : parseInt(this.props.data.default_value, 10);

    if (this.props.mutable) {
      props.ref = "child_ref_" + this.props.data.field_name;
    }

    let datalist = [];
    for (var i=parseInt(this.props.data.min_value, 10); i <= parseInt(this.props.data.max_value, 10); i += parseInt(this.props.data.step, 10)) {
      datalist.push(i);
    }

    let oneBig = 100 / (datalist.length - 1);

    let _datalist = datalist.map((d,idx) => {
      return <option key={props.list+'_'+idx}>{d}</option>
    })

    let visible_marks = datalist.map((d,idx) => {
      let option_props = {};
      let w = oneBig;
      if (idx === 0 || idx === datalist.length-1)
        w = oneBig/2;
      option_props.key = props.list+'_label_'+idx;
      option_props.style = {width: w + '%'};
      if (idx === datalist.length-1)
        option_props.style = {width: w + '%', textAlign: 'right'};
      return <label {...option_props}>{d}</label>
    })

    return this.renderWithSortable(
      <div className="rfb-item">
        { !this.props.mutable &&
          <HeaderBar parent={this.props.parent} editModeOn={this.props.editModeOn} data={this.props.data} onDestroy={this.props._onDestroy} onEdit={this.props.onEdit} static={this.props.data.static} required={this.props.data.required} />
        }
        <div className="form-group">
          <label>
            {this.props.data.label}
            { (this.props.data.hasOwnProperty('required') && this.props.data.required === true) &&
              <span className="label-required label label-danger">Required</span>
            }
          </label>
          <div className="range">
            <div className="clearfix">
              <span className="pull-left">{this.props.data.min_label}</span>
              <span className="pull-right">{this.props.data.max_label}</span>
            </div>
            <SliderNativeBootstrap
              name={props.name}
              value={props.defaultValue}
              step={this.props.data.step}
              max={this.props.data.max_value}
              min={this.props.data.min_value} />
          </div>
          <div className="visible_marks">
            {visible_marks}
          </div>
          <datalist id={props.list}>
            {_datalist}
          </datalist>
        </div>
      </div>
    );
  }
})


FormElements.Header = Header;
FormElements.Paragraph = Paragraph;
FormElements.Label = Label;
FormElements.LineBreak = LineBreak;
FormElements.TextInput = TextInput;
FormElements.NumberInput = NumberInput;
FormElements.TextArea = TextArea;
FormElements.Dropdown = Dropdown;
FormElements.Signature = Signature;
FormElements.Checkboxes = Checkboxes;
FormElements.DatePicker = DatePicker;
FormElements.RadioButtons = RadioButtons;
FormElements.Rating = Rating;
FormElements.Tags = Tags;
FormElements.HyperLink = HyperLink;
FormElements.Download = Download;
FormElements.Camera = Camera;
FormElements.Range = Range;

module.exports = FormElements;
