import {
  IsPostalCode,
  IsString
} from "class-validator";
import { Column } from "typeorm";
import ValidatorJS from 'validator';
import { config } from '../../config';
import { AddressCityEmptyError, AddressCountryEmptyError, AddressFirstLineEmptyError, AddressPostalCodeEmptyError, AddressPostalCodeInvalidError } from '../../errors/AddressErrors';

/**
 * Defines the Address class.
 * Implemented this way to prevent any formatting differences.
*/
export class Address {
  /**
   * The address's first line.
   * Containing the street and house number.
   */
  @Column({ nullable: true })
  @IsString()
  address1?: string;

  /**
   * The address's second line.
   * Containing optional information.
   */
  @Column({ nullable: true })
  @IsString()
  address2?: string;

  /**
   * The address's postal code.
   * This will get checked against the postal code syntax for the configured country.
   */
  @Column({ nullable: true })
  @IsString()
  @IsPostalCode(config.postalcode_validation_countrycode)
  postalcode: string;

  /**
   * The address's city.
   */
  @Column({ nullable: true })
  @IsString()
  city: string;

  /**
   * The address's country.
   */
  @Column({ nullable: true })
  @IsString()
  country: string;

  public reset() {
    this.address1 = null;
    this.address2 = null;
    this.city = null;
    this.country = null;
    this.postalcode = null;
  }

  /**
   * Checks if this is a valid address
   */
  public static isValidAddress(address: Address): Boolean {
    if (address == null) { return false; }
    if (address.address1 == null || address.city == null || address.country == null || address.postalcode == null) { return false; }
    if (ValidatorJS.isPostalCode(address.postalcode, config.postalcode_validation_countrycode) == false) { return false; }
    return true;
  }

  /**
   * This function validates addresses.
   * This is a workaround for non-existant class validation for embedded entities.
   * @param address The address that shall get validated.
   */
  public static validate(address: Address) {
    if (address == null) { return; }
    if (address.address1 == null && address.city == null && address.country == null && address.postalcode == null) { return; }
    if (address.address1 == null) { throw new AddressFirstLineEmptyError(); }
    if (address.postalcode == null) { throw new AddressPostalCodeEmptyError(); }
    if (address.city == null) { throw new AddressCityEmptyError(); }
    if (address.country == null) { throw new AddressCountryEmptyError(); }
    if (ValidatorJS.isPostalCode(address.postalcode.toString(), config.postalcode_validation_countrycode) == false) { throw new AddressPostalCodeInvalidError(); }
  }
}
