'use strict';

import {Observable} from 'rxjs';
import {ValidationError} from './ValidationError';

export class ValidationResult {

  protected _errors: ValidationError[];

  constructor(errors?: ValidationError[]) {
    this._errors = errors || [];
  }

  get isValid(): boolean {
    return !this._errors.length;
  }

  get errors(): ValidationError[] {
    return this._errors;
  }

  asObservable(): Observable<ValidationResult> {
    return Observable.of(this);
  }

  merge(result: ValidationResult): ValidationResult {
    this._errors = this._errors.concat(result.errors);
    return this;
  }

  addError(error: ValidationError): ValidationResult {
    this._errors.push(error);
    return this;
  }

  getInvalidProperties(): string[] {
    return this._errors.reduce((properties, error) => {
      if (properties.indexOf(error.property) === -1) {
        properties.push(error.property);
      }
      return properties;
    }, []);
  }

  getPropertyErrors(propertyName: string): ValidationError[] {
    return this._errors.reduce((errors, error) => {
      if (error && error.property === propertyName) {
        errors.push(error);
      }
      return errors;
    }, []);
  }

  toJSON() {
    return {
      isValid: this.isValid,
      errors: this.errors.map(error => error.toJSON())
    };
  }

  static create(errors?: ValidationError[]): ValidationResult {
    return new ValidationResult(errors);
  }
}