import {
	isEmpty,
	indexOf,
	defaults,
} from "lodash";

var defaultOptions = { source: "wpseoScriptData.analysis.plugins.replaceVars", scope: [], aliases: [] };

/**
 * Constructs the replace var.
 *
 * @param {string} placeholder The placeholder to search for.
 * @param {string} replacement The name of the property to search for as an replacement.
 * @param {object} [options] The options to be used to determine things as scope, source and search for aliases.
 * @constructor
 */
var ReplaceVar = function( placeholder, replacement, options ) {
	this.placeholder = placeholder;
	this.replacement = replacement;
	this.options = defaults( options, defaultOptions );
};

/**
 * Gets the placeholder for the current replace var.
 *
 * @param {bool} [includeAliases] Whether or not to include aliases when getting the placeholder.
 * @returns {string} The placeholder.
 */
ReplaceVar.prototype.getPlaceholder = function( includeAliases ) {
	includeAliases = includeAliases || false;

	if ( includeAliases && this.hasAlias() ) {
		return this.placeholder + "|" + this.getAliases().join( "|" );
	}

	return this.placeholder;
};

/**
 * Override the source of the replacement.
 *
 * @param {string} source The source to use.
 *
 * @returns {void}
 */
ReplaceVar.prototype.setSource = function( source ) {
	this.options.source = source;
};

/**
 * Determines whether or not the replace var has a scope defined.
 *
 * @returns {boolean} Returns true if a scope is defined and not empty.
 */
ReplaceVar.prototype.hasScope = function() {
	return ! isEmpty( this.options.scope );
};

/**
 * Adds a scope to the replace var.
 *
 * @param {string} scope The scope to add.
 *
 * @returns {void}
 */
ReplaceVar.prototype.addScope = function( scope ) {
	if ( ! this.hasScope() ) {
		this.options.scope = [];
	}

	this.options.scope.push( scope );
};

/**
 * Determines whether the passed scope is defined in the replace var.
 *
 * @param {string} scope The scope to check for.
 * @returns {boolean} Whether or not the passed scope is present in the replace var.
 */
ReplaceVar.prototype.inScope = function( scope ) {
	if ( ! this.hasScope() ) {
		return true;
	}

	return indexOf( this.options.scope, scope ) > -1;
};

/**
 * Determines whether or not the current replace var has an alias.
 *
 * @returns {boolean} Whether or not the current replace var has one or more aliases.
 */
ReplaceVar.prototype.hasAlias = function() {
	return ! isEmpty( this.options.aliases );
};

/**
 * Adds an alias to the replace var.
 *
 * @param {string} alias The alias to add.
 *
 * @returns {void}
 */
ReplaceVar.prototype.addAlias = function( alias ) {
	if ( ! this.hasAlias() ) {
		this.options.aliases = [];
	}

	this.options.aliases.push( alias );
};

/**
 * Gets the aliases for the current replace var.
 *
 * @returns {array} The aliases available to the replace var.
 */
ReplaceVar.prototype.getAliases = function() {
	return this.options.aliases;
};

export default ReplaceVar;
