/*
 *  Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 *  WSO2 Inc. licenses this file to you under the Apache License,
 *  Version 2.0 (the "License"); you may not use this file except
 *  in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 */

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
// Material UI Components
import Typography from 'material-ui/Typography';
import Grid from 'material-ui/Grid';
// Localization
import { FormattedMessage } from 'react-intl';
// App Components
import TemplateGroupThumbnail from './TemplateGroupThumbnail';
import ProgressDisplay from '../../common/ProgressDisplay';
import ErrorDisplay from '../../common/error/ErrorDisplay';
import Header from '../../common/Header';
// App Utils
import BusinessRulesUtilityFunctions from '../../../utils/BusinessRulesUtilityFunctions';
// App APIs
import BusinessRulesAPI from '../../../api/BusinessRulesAPI';
// App Constants
import BusinessRulesConstants from '../../../constants/BusinessRulesConstants';
// Styles
import Styles from '../../../style/Styles';
import '../../../index.css';

/**
 * App context
 */
const appContext = window.contextPath;

/**
 * Represents the page that allows to select a Template Group
 */
export default class TemplateGroupSelector extends Component {
  constructor(props) {
    super(props);
    this.state = {
      mode: this.props.match.params.mode,
      templateGroups: [],

      // Loaded state of page and related Error code
      hasLoaded: false,
      errorCode: BusinessRulesConstants.ERROR_CODES.UNKNOWN,
    };
  }

  componentDidMount() {
    this.loadTemplateGroups();
  }

  /**
   * Loads available Template Groups
   */
  loadTemplateGroups() {
    new BusinessRulesAPI(BusinessRulesConstants.BASE_URL)
      .getTemplateGroups()
      .then((templateGroupsResponse) => {
        const filteredTemplateGroups = this.filterTemplateGroups(
          templateGroupsResponse.data[2],
        );
        this.setState({
          templateGroups: filteredTemplateGroups,
          hasLoaded: true,
          errorCode: BusinessRulesConstants.ERROR_CODES.NONE,
        });
      })
      .catch((error) => {
        this.setState({
          hasLoaded: true,
          errorCode: BusinessRulesUtilityFunctions.getErrorDisplayCode(error),
        });
      });
  }

  /**
   * Filters Template Groups by removing unnecessary template groups.
   * Template Groups are removed for filtering, based on the following criteria.
   *      1.  Template Groups that don't have at least one Input Rule Template & one Output Rule Template,
   *          when the mode is 'from scratch'
   *      2.  Template Groups that don't have at least one 'template' type of Rule Template,
   *          when the mode is 'from template'
   * @param {Array} templateGroups        Unfiltered array of available Template Groups
   * @returns {Array}                     Filtered array of Template Groups
   */
  filterTemplateGroups(templateGroups) {
    const filteredTemplateGroups = [];
    for (let i = 0; i < templateGroups.length; i++) {
      let templateRuleTemplatesCount = 0;
      let inputRuleTemplatesCount = 0;
      let outputRuleTemplatesCount = 0;
      for (const ruleTemplate of templateGroups[i].ruleTemplates) {
        if (
          ruleTemplate.type
          === BusinessRulesConstants.RULE_TEMPLATE_TYPE_TEMPLATE
        ) {
          templateRuleTemplatesCount++;
        } else if (
          ruleTemplate.type === BusinessRulesConstants.RULE_TEMPLATE_TYPE_INPUT
        ) {
          inputRuleTemplatesCount++;
        } else if (
          ruleTemplate.type === BusinessRulesConstants.RULE_TEMPLATE_TYPE_OUTPUT
        ) {
          outputRuleTemplatesCount++;
        }
      }
      if (
        (this.state.mode
          === BusinessRulesConstants.BUSINESS_RULE_TYPE_TEMPLATE
          && templateRuleTemplatesCount > 0)
        || (this.state.mode
          === BusinessRulesConstants.BUSINESS_RULE_TYPE_SCRATCH
          && inputRuleTemplatesCount > 0
          && outputRuleTemplatesCount > 0)
      ) {
        filteredTemplateGroups.push(templateGroups[i]);
      }
    }
    return filteredTemplateGroups;
  }

  /**
   * Returns a Template Group thumbnail, for the given templateGroup object
   * @param {Object} templateGroup        Object which has details of a Template Group
   * @returns {Component}                 Link to the Business Rule creation page
   */
  displayTemplateGroupThumbnail(templateGroup) {
    let specificPath;
    if (
      this.state.mode === BusinessRulesConstants.BUSINESS_RULE_TYPE_TEMPLATE
    ) {
      specificPath = 'businessRuleFromTemplateForm';
    } else {
      specificPath = 'businessRuleFromScratchForm';
    }

    return (
      <Link
        to={
          `${appContext}/${specificPath}/${
          BusinessRulesConstants.BUSINESS_RULE_FORM_MODE_CREATE
          }` + `/templateGroup/${templateGroup.uuid}/businessRule`
        }
        style={{ textDecoration: 'none' }}
      >
        <TemplateGroupThumbnail
          key={templateGroup.uuid}
          name={templateGroup.name}
          uuid={templateGroup.uuid}
          description={templateGroup.description || ''}
        />
      </Link>
    );
  }

  /**
   * Returns available template groups when at least one is available, otherwise a message
   * @returns {Component}     Grid
   */
  displayGridContent() {
    if (this.state.templateGroups.length > 0) {
      return (
        <Grid container justify="center" spacing={0}>
          {this.state.templateGroups.map(templateGroup => (
            <Grid item key={templateGroup.uuid}>
              {this.displayTemplateGroupThumbnail(templateGroup)}
            </Grid>
          ))}
        </Grid>
      );
    }
    return (
      <Grid container justify="center" spacing={0}>
        <Grid item>
          <Typography>
            <FormattedMessage
              id="template.nosuitable"
              defaultMessage=" No Suitable Template Groups found"
            />
          </Typography>
        </Grid>
      </Grid>
    );
  }

  /**
   * Displays content of the page
   * @returns {Component}     Content of the page
   */
  displayContent() {
    if (this.state.hasLoaded) {
      if (this.state.errorCode === BusinessRulesConstants.ERROR_CODES.NONE) {
        return (
          <center>
            <Typography type="headline">
              <FormattedMessage
                id="template.select"
                defaultMessage="Select a Template Group"
              />
            </Typography>
            <br />
            <Grid container style={Styles.grid.root}>
              <Grid item xs={12}>
                {this.displayGridContent()}
              </Grid>
            </Grid>
          </center>
        );
      }
      return <ErrorDisplay errorCode={this.state.errorCode} />;

    } else {
      return <ProgressDisplay />;
    }
  }

  render() {
    return (
      <div>
        <Header />
        <br />
        <br />
        <div>{this.displayContent()}</div>
      </div>
    );
  }
}

TemplateGroupSelector.propTypes = {
  match: PropTypes.shape({
    params: PropTypes.shape({
      mode: PropTypes.oneOf([
        BusinessRulesConstants.BUSINESS_RULE_TYPE_TEMPLATE,
        BusinessRulesConstants.BUSINESS_RULE_TYPE_SCRATCH,
      ]),
    }),
  }).isRequired,
};
