import { EntityMetadata } from './EntityMetadata';
import { NamingStrategyInterface } from '../naming-strategy/NamingStrategyInterface';
import { ExclusionMetadataArgs } from '../metadata-args/ExclusionMetadataArgs';

/**
 * Exclusion metadata contains all information about table's exclusion constraints.
 */
export class ExclusionMetadata {
	// ---------------------------------------------------------------------
	// Public Properties
	// ---------------------------------------------------------------------

	/**
	 * Entity metadata of the class to which this exclusion constraint is applied.
	 */
	entityMetadata: EntityMetadata;

	/**
	 * Target class to which metadata is applied.
	 */
	target?: Function | string;

	/**
	 * Exclusion expression.
	 */
	expression: string;

	/**
	 * User specified exclusion constraint name.
	 */
	givenName?: string;

	/**
	 * Final exclusion constraint name.
	 * If exclusion constraint name was given by a user then it stores normalized (by naming strategy) givenName.
	 * If exclusion constraint name was not given then its generated.
	 */
	name: string;

	// ---------------------------------------------------------------------
	// Constructor
	// ---------------------------------------------------------------------

	constructor(options: {
		entityMetadata: EntityMetadata;
		args?: ExclusionMetadataArgs;
	}) {
		this.entityMetadata = options.entityMetadata;

		if (options.args) {
			this.target = options.args.target;
			this.expression = options.args.expression;
			this.givenName = options.args.name;
		}
	}

	// ---------------------------------------------------------------------
	// Public Build Methods
	// ---------------------------------------------------------------------

	/**
	 * Builds some depend exclusion constraint properties.
	 * Must be called after all entity metadata's properties map, columns and relations are built.
	 */
	build(namingStrategy: NamingStrategyInterface): this {
		this.name = this.givenName
			? this.givenName
			: namingStrategy.exclusionConstraintName(this.entityMetadata.tableName, this.expression);
		return this;
	}
}
