//React
import * as React from 'react';
import * as ReactDOM from 'react-dom';
//Wijmo
import * as wjcCore from 'wijmo/wijmo';
//Application
import { DataSvc } from '../services/DataSvc';

export class Grouping extends React.Component<any, any> {

    fieldNames = DataSvc.default.getNames();
    cvGrouping = new wjcCore.CollectionView(DataSvc.default.getData(20));
    groupItems: any;

    constructor(props) {
        super(props);
        this.groupItems = this.cvGrouping.items;

        // update the group list
        this.cvGrouping.collectionChanged.addHandler(() => {
            this.groupItems = this.cvGrouping.items;
            if (this.cvGrouping.groups && this.cvGrouping.groups.length > 0) {
                this.groupItems = [];
                for (var i = 0; i < this.cvGrouping.groups.length; i++) {
                    this._addGroup(this.cvGrouping.groups[i]);
                }
            }
        });
    }

    avgAmount(item: any) {
        // it only works when the item is a group item.
        if (!this.isGroupItem(item)) {
            return;
        }

        // get the average value of group amount values.
        var avg = item.getAggregate(wjcCore.Aggregate.Avg, 'amount');
        return wjcCore.Globalize.format(avg, '');
    };

    isGroupItem(item: any): boolean {
        return item instanceof wjcCore.CollectionViewGroup;
    };

     applyGrouping(event) {
        var gd,
            fieldName = event.target.value;

        gd = this.cvGrouping.groupDescriptions;

        if (!fieldName) {
            // clear all the group settings.
            gd.splice(0, gd.length);
            this.forceUpdate();
            return;
        }

        if (this._findGroup(fieldName) >= 0) {
            return;
        }

        if (fieldName == 'amount') {
            // when grouping by amount, use ranges instead of specific values
            gd.push(new wjcCore.PropertyGroupDescription(fieldName, function (item, propName) {
                var value = item[propName]; // amount
                if (value > 1000) return 'Large Amounts';
                if (value > 100) return 'Medium Amounts';
                if (value > 0) return 'Small Amounts';
                return 'Negative Amounts';
            }));
        }
        else {
            // group by specific property values
            gd.push(new wjcCore.PropertyGroupDescription(fieldName));
        }

        this.forceUpdate();
    }

    // check whether the group with the specified property name already exists.
    private _findGroup(propName: string) {
        var gd = this.cvGrouping.groupDescriptions;
        for (var i = 0; i < gd.length; i++) {
            if (gd[i].propertyName === propName) {
                return i;
            }
        }
        return -1;
    }

    private _addGroup(g: any) {
        this.groupItems.push(g);
        if (g.isBottomLevel) {
            for (var i = 0; i < g.items.length; i++) {
                this.groupItems.push(g.items[i]);
            }
        }
        else {
            for (var i = 0; i < g.groups.length; i++) {
                this._addGroup(g.groups[i]);
            }
        }
    }

    render() {
        return <div>
              <h2>Grouping</h2>
              <p>
                  The CollectionView class, like the one in .NET, implements the ICollectionView
                  interface to support grouping. To enable grouping, add one or more <a target="_blank"
                                                                                        href="http://wijmo.com/5/docs/topic/wijmo.collections.GroupDescription.Class.html">
                      GroupDescription
                  </a> objects to an array and pass it to the <b>CollectionView.groupDescriptions</b> property.
                  You must also set the grid's <b>showGroups</b> property to true when creating
                  the grid instance, as the default value is false.
              </p>
              <p>
                  <b>GroupDescription</b> objects are flexible, allowing you to group data
                  based on value or on grouping functions.
              </p>
              <p>
                  The example below groups the collection by whichever field you select from the
                  list. The grid shows not only the item's content but also group information:
                  the group name and the average value of the amount for the group appear in the
                  group header row.
              </p>
              <p>
                  <b>Notes</b>: Selecting one item in the list adds a new instance of the
                  GroupDescription. Subsequent selections nest groups. If you select an item from
                  the list for which a GroupDescription object already exists, nothing happens.
                  In order to clear the group settings, select the first item in the list.
              </p>
            <div className="row">
                <div className="col-md-6">
                    <ul className="nav nav-tabs" role="tablist">
                        <li className="active"><a href="#ftJsx" role="tab" data-toggle="tab">JSX</a></li>
                        <li><a href="#ftJs" role="tab" data-toggle="tab">TS</a></li>
                    </ul>
                    <div className="tab-content">
                        <div className="tab-pane active pane-content" id="ftJsx">
                            {'  <div className="row-fluid well">\n'}
                            {'      <select className="form-control" onChange={(e) => { this.applyGrouping(e) }} >\n'}
                            {'          <option value="" >Please choose the field by which to group.</option>\n'}
                            {'          {this.fieldNames.map((fieldName, index) => {\n'}
                            {'              return <option key={index} value={fieldName}>\n'}
                            {'                  {fieldName}\n'}
                            {'              </option>\n'}
                            {'          })}\n'}
                            {'      </select>\n'}
                            {'  </div>\n'}
                            {'  <div className="sGrid">\n'}
                            {'      <table className="table table-condensed table-bordered">\n'}
                            {'          <thead>\n'}
                            {'              <tr className="active">\n'}
                            {'                  {this.fieldNames.map((fieldName, index) => {\n'}
                            {'                      return <th key={index} className="text-center">\n'}
                            {'                          {fieldName}\n'}
                            {'                      </th>\n'}
                            {'                  })}\n'}
                            {'              </tr>\n'}
                            {'          </thead>\n'}
                            {'          <tbody>\n'}
                            {'              {this.groupItems.map((item, idx1) => {\n'}
                            {'                  let groupSize = 0;\n'}
                            {'                  if (item.items) {\n'}
                            {'                      groupSize = item.items.length;\n'}
                            {'                  }\n'}
                            {'                  return <tr key={idx1}>\n'}
                            {'                      <td className="active" style={{ display: this.isGroupItem(item) ? \'\' : \'none\' }} colSpan={6}>\n'}
                            {'                          <span style={{ display: \'inline-block\', width: (item.level * 25) + \'px\' }}></span>\n'}
                            {'                          <b>{wjcCore.Globalize.format(item.name, \'\')}</b> ({groupSize} items)\n'}
                            {'                   </td>\n'}
                            {'                      <td className="text-center" colSpan={2} style={{ display: this.isGroupItem(item) ? \'\' : \'none\' }} >\n'}
                            {'                          {this.avgAmount(item)}\n'}
                            {'                      </td>\n'}
                            {'                      {this.fieldNames.map((fieldName, idx2) => {\n'}
                            {'                          let itm = wjcCore.Globalize.format(item[fieldName], \'\');\n'}
                            {'                          return <td key={idx2} className="text-center" style={{ display: this.isGroupItem(item) ? \'none\' : \'\' }}>\n'}
                            {'                              {wjcCore.Globalize.format(item[fieldName], \'\')}\n'}
                            {'                          </td>\n'}
                            {'                      })}\n'}
                            {'                  </tr>\n'}
                            {'              })}\n'}
                            {'          </tbody>\n'}
                            {'      </table>\n'}
                            {'  </div>\n'}
                        </div>
                        <div className="tab-pane pane-content" id="ftJs">
                            {'  fieldNames = DataSvc.default.getNames();\n'}
                            {'  cvGrouping = new wjcCore.CollectionView(DataSvc.default.getData(20));\n'}
                            {'   groupItems: any;\n'}
                            {'\n'}
                            {'  constructor(props) {\n'}
                            {'      super(props);\n'}
                            {'      this.groupItems = this.cvGrouping.items;\n'}
                            {'      // update the group list\n'}
                            {'      this.cvGrouping.collectionChanged.addHandler(() => {\n'}
                            {'          this.groupItems = this.cvGrouping.items;\n'}
                            {'          if (this.cvGrouping.groups && this.cvGrouping.groups.length > 0) {\n'}
                            {'              this.groupItems = [];\n'}
                            {'              for (var i = 0; i < this.cvGrouping.groups.length; i++) {\n'}
                            {'                  this._addGroup(this.cvGrouping.groups[i]);\n'}
                            {'              }\n'}
                            {'          }\n'}
                            {'      });\n'}
                            {'  }\n'}
                            {'\n'}
                            {'  avgAmount(item: any) {\n'}
                            {'      // it only works when the item is a group item.\n'}
                            {'      if (!this.isGroupItem(item)) {\n'}
                            {'          return;\n'}
                            {'      }\n'}
                            {'\n'}
                            {'      // get the average value of group amount values.\n'}
                            {'      var avg = item.getAggregate(wjcCore.Aggregate.Avg, \'amount\');\n'}
                            {'      return wjcCore.Globalize.format(avg, \'\');\n'}
                            {'  };\n'}
                            {'\n'}
                            {'  isGroupItem(item: any): boolean {\n'}
                            {'      return item instanceof wjcCore.CollectionViewGroup;\n'}
                            {'  };\n'}
                            {'\n'}
                            {'   applyGrouping(event) {\n'}
                            {'      var gd,\n'}
                            {'          fieldName = event.target.value;\n'}
                            {'\n'}
                            {'      gd = this.cvGrouping.groupDescriptions;\n'}
                            {'\n'}
                            {'      if (!fieldName) {\n'}
                            {'          // clear all the group settings.\n'}
                            {'          gd.splice(0, gd.length);\n'}
                            {'          this.forceUpdate();\n'}
                            {'          return;\n'}
                            {'      }\n'}
                            {'\n'}
                            {'      if (this._findGroup(fieldName) >= 0) {\n'}
                            {'          return;\n'}
                            {'      }\n'}
                            {'\n'}
                            {'      if (fieldName == \'amount\') {\n'}
                            {'          // when grouping by amount, use ranges instead of specific values\n'}
                            {'          gd.push(new wjcCore.PropertyGroupDescription(fieldName, function (item, propName) {\n'}
                            {'              var value = item[propName]; // amount\n'}
                            {'              if (value > 1000) return \'Large Amounts\';\n'}
                            {'              if (value > 100) return \'Medium Amounts\';\n'}
                            {'              if (value > 0) return \'Small Amounts\';\n'}
                            {'              return \'Negative Amounts\';\n'}
                            {'          }));\n'}
                            {'      }\n'}
                            {'      else {\n'}
                            {'          // group by specific property values\n'}
                            {'          gd.push(new wjcCore.PropertyGroupDescription(fieldName));\n'}
                            {'      }\n'}
                            {'\n'}
                            {'      this.forceUpdate();\n'}
                            {'  }\n'}
                            {'\n'}
                            {'  // check whether the group with the specified property name already exists.\n'}
                            {'  private _findGroup(propName: string) {\n'}
                            {'      var gd = this.cvGrouping.groupDescriptions;\n'}
                            {'      for (var i = 0; i < gd.length; i++) {\n'}
                            {'          if (gd[i].propertyName === propName) {\n'}
                            {'              return i;\n'}
                            {'          }\n'}
                            {'      }\n'}
                            {'      return -1;\n'}
                            {'  }\n'}
                            {'\n'}
                            {'  private _addGroup(g: any) {\n'}
                            {'      this.groupItems.push(g);\n'}
                            {'      if (g.isBottomLevel) {\n'}
                            {'          for (var i = 0; i < g.items.length; i++) {\n'}
                            {'              this.groupItems.push(g.items[i]);\n'}
                            {'          }\n'}
                            {'      }\n'}
                            {'      else {\n'}
                            {'          for (var i = 0; i < g.groups.length; i++) {\n'}
                            {'              this._addGroup(g.groups[i]);\n'}
                            {'          }\n'}
                            {'      }\n'}
                            {'  }\n'}
                        </div>
                    </div>
                </div>
                <div className="col-md-6">
                    <h4>Result (live):</h4>
                    <div className="row-fluid well">
                        <select className="form-control" onChange={(e) => { this.applyGrouping(e) }} >
                            <option value="" >Please choose the field by which to group.</option>
                            {this.fieldNames.map((fieldName, index) => {
                                return <option key={index} value={fieldName}>
                                    {fieldName}
                                </option>
                            })}
                         </select>
                    </div>
                    <div className="sGrid">
                        <table className="table table-condensed table-bordered">
                            <thead>
                                <tr className="active">
                                    {this.fieldNames.map((fieldName, index) => {                                        
                                        return <th key={index} className="text-center">
                                            {fieldName}
                                        </th>
                                    })}
                                </tr>
                            </thead>
                            <tbody>
                                {this.groupItems.map((item, idx1) => {
                                    let groupSize = 0;
                                    if (item.items) {
                                        groupSize = item.items.length;
                                    }
                                    return <tr key={idx1}>
                                        <td className="active" style={{ display: this.isGroupItem(item) ? '' : 'none' }} colSpan={6}>
                                            <span style={{ display: 'inline-block', width: (item.level * 25) + 'px' }}></span>
                                            <b>{wjcCore.Globalize.format(item.name, '')}</b> ({groupSize} items)
                                             </td>
                                        <td className="text-center" colSpan={2} style={{ display: this.isGroupItem(item) ? '' : 'none' }} >
                                                 { this.avgAmount(item) }
                                         </td>
                                        {this.fieldNames.map((fieldName, idx2) => {
                                            let itm = wjcCore.Globalize.format(item[fieldName], '');
                                            return <td key={idx2} className="text-center" style={{ display: this.isGroupItem(item) ? 'none' : '' }}>
                                                {wjcCore.Globalize.format(item[fieldName], '')}
                                            </td>
                                        })}
                                    </tr>
                                })}
                            </tbody>
                        </table>
                    </div>
                </div>
            </div >
        </div >;

    }
}

