/*
 * Copyright 2017-present Open Networking Foundation

 * Licensed 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 * as _ from 'lodash';
import {IXosResourceService} from '../../datasources/rest/model.rest';
import {IXosSgNode} from '../interfaces';
import {IXosConfirm} from '../../core/confirm/confirm.service';

export interface IXosNodePositioner {
  positionNodes(svg: {width: number, height: number}, nodes: any[]): ng.IPromise<IXosSgNode[]>;
}

export class XosNodePositioner implements IXosNodePositioner {
  static $inject = [
    '$log',
    '$q',
    'ModelRest',
    'XosConfirm'
  ];

  constructor (
    private $log: ng.ILogService,
    private $q: ng.IQService,
    private ModelRest: IXosResourceService,
    private XosConfirm: IXosConfirm
  ) {
    this.$log.info('[XosNodePositioner] Setup');
  }

  public positionNodes(svg: {width: number, height: number}, nodes: IXosSgNode[]): ng.IPromise<IXosSgNode[]> {

    const d =  this.$q.defer();

    this.getConstraints()
      .then(constraints => {
        const hStep = this.getHorizontalStep(svg.width, constraints);
        const positionConstraints = _.reduce(constraints, (all: any, horizontalConstraint: string | string[], i: number) => {
          // NOTE it's a single element, leave it in the middle
          if (angular.isString(horizontalConstraint)) {
            all[horizontalConstraint] = {
              x: (i + 1) * hStep,
              y: svg.height / 2,
              fixed: true
            };
          }
          else {
            const verticalConstraints = horizontalConstraint;
            const vStep = this.getVerticalStep(svg.height, verticalConstraints);
            _.forEach(verticalConstraints, (verticalConstraint: string, v: number) => {
              if (angular.isString(verticalConstraint)) {
                all[verticalConstraint] = {
                  x: (i + 1) * hStep,
                  y: (v + 1) * vStep,
                  fixed: true
                };
              }
            });
          }
          return all;
        }, {});

        // find the nodes that don't have a position defined and put them at the bottom
        const allServiceNodes = _.reduce(nodes, (all: string[], n: IXosSgNode) => {
          if (n.type === 'service') {
            all.push(n.data.name);
          }
          return all;
        }, []);
        const positionedNodes = Object.keys(positionConstraints);
        const unpositionedNodes = _.difference(allServiceNodes, positionedNodes);

        _.forEach(unpositionedNodes, (node: string, i: number) => {
          const hStep = this.getHorizontalStep(svg.width, unpositionedNodes);
          positionConstraints[node] = {
            x: (i + 1) * hStep,
            y: svg.height - 50,
            fixed: true
          };
        });

        d.resolve(_.map(nodes, n => {
          return angular.merge(n, positionConstraints[n.data.name]);
        }));
      })
      .catch(e => {
        this.$log.error(`[XosNodePositioner] Error retrieving constraints`, e);
      });

    return d.promise;
  }

  private getConstraints(): ng.IPromise<any[]> {
    const d = this.$q.defer();
    this.ModelRest.getResource('/core/servicegraphconstraints').query().$promise
      .then(res => {
        d.resolve(JSON.parse(res[0].constraints));
      })
      .catch(e => {
        this.XosConfirm.open({
          header: 'Error in graph constraints config',
          text: `
            There was an error in the settings you provided as graph constraints. 
            Please check the declaration of the <code>"Graph Constraints"</code> model. <br/> 
            The error was: <br/><br/>
            <code>${e}</code>
            <br/><br/>
            Please fix it to see the graph.`,
          actions: []
        });
        d.reject(e);
      });
    return d.promise;
  }

  private getHorizontalStep(svgWidth: number, constraints: any[]) {
    return svgWidth / (constraints.length + 1);
  }

  private getVerticalStep(svgHeight: number, verticalConstraints: string[]) {
    // NOTE verticalConstraints represent the vertical part (the nested array)
    return svgHeight / (verticalConstraints.length + 1);
  }
}
