/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */
package org.apache.sling.feature.extension.apiregions.api.config;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonException;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.json.JsonValue;

import org.apache.felix.cm.json.Configurations;

/**
 * Instances of this class represent a single configuration property
 * This class is not thread safe.
 */
public class PropertyDescription extends DescribableEntity {
	
	/** The property type */
	private PropertyType type;

	/** The property cardinality */
    private int cardinality;

	/** The optional variable */
    private String variable;

	/** The optional range */
	private Range range;

	/** The required includes for an array/collection (optional) */
	private String[] includes;

	/** The required excludes for an array/collection (optional) */
	private String[] excludes;

	/** The optional list of options for the value */
	private List<Option> options;
	
	/** The optional regex */
	private Pattern pattern;

	/** Required? */
	private boolean required;
    
    /** 
     * The optional default value 
     * @since 1.2
     */
    private Object defaultValue;

    /** 
     * The validation mode. 
     * @since 1.2
     */
    private Mode mode;

    /**
     * The placeholder policy
     * @since 1.3
     */
    private PlaceholderPolicy placeholderPolicy;

	/**
     * A pattern to validate values which contain substitution placeholders
     * @since 1.3
     */
	private Pattern placeholderPattern;

    /**
     * Create a new description
     */
    public PropertyDescription() {
        this.setDefaults();
    }

    void setDefaults() {
        super.setDefaults();
		this.setType(PropertyType.STRING);
        this.setCardinality(1);
        this.setRequired(false);
        this.setPlaceholderPolicy(PlaceholderPolicy.DEFAULT);
    }

    /**
     * Clear the object and reset to defaults
     */
    @Override
	public void clear() {
        super.clear();
		this.setVariable(null);
		this.setRange(null);
		this.setIncludes(null);
		this.setExcludes(null);
		this.setOptions(null);
		this.setRegex(null);
        this.setDefaultValue(null);
        this.setMode(null);
    }

	/**
	 * Extract the metadata from the JSON object.
	 * This method first calls {@link #clear()}
	 * @param jsonObj The JSON Object
	 * @throws IOException If JSON parsing fails
	 */
    @Override
	public void fromJSONObject(final JsonObject jsonObj) throws IOException {
        super.fromJSONObject(jsonObj);
        try {
			this.setVariable(this.getString(InternalConstants.KEY_VARIABLE));
			this.setCardinality(this.getInteger(InternalConstants.KEY_CARDINALITY, this.getCardinality()));
			this.setRequired(this.getBoolean(InternalConstants.KEY_REQUIRED, this.isRequired()));
			
			final String typeVal = this.getString(InternalConstants.KEY_TYPE);
			if ( typeVal != null ) {
                this.setType(PropertyType.valueOf(typeVal.toUpperCase()));				
			}
			final JsonValue rangeVal = this.getAttributes().remove(InternalConstants.KEY_RANGE);
			if ( rangeVal != null ) {
				final Range range = new Range();
				range.fromJSONObject(rangeVal.asJsonObject());
				this.setRange(range);
			}
			final JsonValue incs = this.getAttributes().remove(InternalConstants.KEY_INCLUDES);
			if ( incs != null ) {
				final List<String> list = new ArrayList<>();
				for(final JsonValue innerVal : incs.asJsonArray()) {
                    list.add(getString(innerVal));
                }
                this.setIncludes(list.toArray(new String[list.size()]));
			}
			final JsonValue excs = this.getAttributes().remove(InternalConstants.KEY_EXCLUDES);
			if ( excs != null ) {
				final List<String> list = new ArrayList<>();
				for(final JsonValue innerVal : excs.asJsonArray()) {
                    list.add(getString(innerVal));
                }
                this.setExcludes(list.toArray(new String[list.size()]));
			}
			final JsonValue opts = this.getAttributes().remove(InternalConstants.KEY_OPTIONS);
			if ( opts != null ) {
				final List<Option> list = new ArrayList<>();
				for(final JsonValue innerVal : opts.asJsonArray()) {
					final Option o = new Option();
					o.fromJSONObject(innerVal.asJsonObject());
					list.add(o);
                }
				this.setOptions(list);
			}
			this.setRegex(this.getString(InternalConstants.KEY_REGEX));
            final JsonValue dv = this.getAttributes().remove(InternalConstants.KEY_DEFAULT);
            if ( dv != null ) {
                this.setDefaultValue(Configurations.convertToObject(dv));
            }
			final String modeVal = this.getString(InternalConstants.KEY_MODE);
			if ( modeVal != null ) {
                this.setMode(Mode.valueOf(modeVal.toUpperCase()));				
			}
			final String policyVal = this.getString(InternalConstants.KEY_PLACEHOLDER_POLICY);
			if ( policyVal != null ) {
                this.setPlaceholderPolicy(PlaceholderPolicy.valueOf(policyVal.toUpperCase()));
			}
			this.setPlaceholderRegex(this.getString(InternalConstants.KEY_PLACEHOLDER_REGEX));
 		} catch (final JsonException | IllegalArgumentException e) {
            throw new IOException(e);
        }
	}
	
    /**
     * Convert this object into JSON
     *
     * @return The json object builder
     * @throws IOException If generating the JSON fails
     */
    @Override
    JsonObjectBuilder createJson() throws IOException {
		final JsonObjectBuilder objectBuilder = super.createJson();

		if ( this.getType() != null && this.getType() != PropertyType.STRING ) {
			this.setString(objectBuilder, InternalConstants.KEY_TYPE, this.getType().name());
	    }
		if ( this.getCardinality() != 1 ) {
			objectBuilder.add(InternalConstants.KEY_CARDINALITY, this.getCardinality());
		}
		if ( this.isRequired() ) {
			objectBuilder.add(InternalConstants.KEY_REQUIRED, this.isRequired());
		}
	    this.setString(objectBuilder, InternalConstants.KEY_VARIABLE, this.getVariable());
		
		if ( this.getRange() != null ) {
			objectBuilder.add(InternalConstants.KEY_RANGE, this.getRange().toJSONObject());
		}
		if ( this.getIncludes() != null && this.getIncludes().length > 0 ) {
			final JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
			for(final String v : this.getIncludes()) {
				arrayBuilder.add(v);
			}
			objectBuilder.add(InternalConstants.KEY_INCLUDES, arrayBuilder);
		}
		if ( this.getExcludes() != null && this.getExcludes().length > 0 ) {
			final JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
			for(final String v : this.getExcludes()) {
				arrayBuilder.add(v);
			}
			objectBuilder.add(InternalConstants.KEY_EXCLUDES, arrayBuilder);
		}
		if ( this.getOptions() != null && !this.getOptions().isEmpty()) {
			final JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
            for(final Option o : this.getOptions()) {
				arrayBuilder.add(o.toJSONObject());
			}
			objectBuilder.add(InternalConstants.KEY_OPTIONS, arrayBuilder);
		}
		this.setString(objectBuilder, InternalConstants.KEY_REGEX, this.getRegex());
		if ( this.getDefaultValue() != null ) {
            objectBuilder.add(InternalConstants.KEY_DEFAULT, Configurations.convertToJsonValue(this.getDefaultValue()));
        }
        if ( this.getMode() != null ) {
            objectBuilder.add(InternalConstants.KEY_MODE, this.getMode().name());
        }
        if ( this.getPlaceholderPolicy() != PlaceholderPolicy.DEFAULT ) {
            objectBuilder.add(InternalConstants.KEY_PLACEHOLDER_POLICY, this.getPlaceholderPolicy().name());
        }
        this.setString(objectBuilder, InternalConstants.KEY_PLACEHOLDER_REGEX, this.getPlaceholderRegex());

        return objectBuilder;
	}

    /**
	 * Get the property type
	 * @return the type
	 */
	public PropertyType getType() {
		return type;
	}

	/**
	 * Set the property type
	 * @param type the type to set
	 */
	public void setType(final PropertyType type) {
		this.type = type == null ? PropertyType.STRING : type;
	}

	/**
	 * Get the cardinality
	 * @return the cardinality
	 */
	public int getCardinality() {
		return cardinality;
	}

	/**
	 * Set the cardinality
     * The default cardinality is {@code 1}. If the value is greater than zero
     * the property can contain up to that number of values.
     * If the cardinality is {@code -1} the property can hold an unlimited number
     * of values.
	 * @param value the cardinality to set
     * @throws IllegalArgumentException If the value is {@code 0} or below {@code -1}.
	 */
	public void setCardinality(final int value) {
        if ( value == 0 || value < -1 ) {
            throw new IllegalArgumentException();
        }
		this.cardinality = value;
	}

	/**
	 * Get the variable
	 * @return the variable or {@code null}
	 */
	public String getVariable() {
		return variable;
	}

	/**
	 * Set the variable
	 * @param variable the variable to set
	 */
	public void setVariable(final String variable) {
		this.variable = variable;
	}

	/**
	 * Get the range
	 * @return the range or {@code null}
	 */
	public Range getRange() {
		return range;
	}

	/**
	 * Set the range
	 * @param range the range to set
	 */
	public void setRange(final Range range) {
		this.range = range;
	}

	/**
	 * Get the includes
	 * @return the includes or {@code null}
	 */
	public String[] getIncludes() {
		return includes;
	}

	/**
	 * Set the includes
	 * @param includes the includes to set
	 */
	public void setIncludes(final String[] includes) {
		this.includes = includes;
	}

	/**
	 * Get the excludes
	 * @return the excludes or {@code null}
	 */
	public String[] getExcludes() {
		return excludes;
	}

	/**
	 * Set the excludes
	 * @param excludes the excludes to set
	 */
	public void setExcludes(final String[] excludes) {
		this.excludes = excludes;
	}

	/**
	 * Get the list of options
	 * @return the options or {@code null}
	 */
	public List<Option> getOptions() {
		return options;
	}

	/**
	 * Set the list of options
	 * @param options the options to set
	 */
	public void setOptions(final List<Option> options) {
		this.options = options;
	}

	/**
	 * Get the regex
	 * @return the regex or {@code null}
	 */
	public String getRegex() {
		return pattern == null ? null : pattern.pattern();
	}

	/**
	 * Set the regex
	 * @param regex the regex to set
     * @throws IllegalArgumentException If the pattern is not valid
	 */
	public void setRegex(final String regex) {
        if ( regex == null ) {
            this.pattern = null;
        } else {
           this.pattern = Pattern.compile(regex);
        }
	}

    /**
     * Get the regex pattern
     * @return The pattern or {@code null}
     */
    public Pattern getRegexPattern() {
        return this.pattern;
    }

	/**
	 * Is this property required?
	 * @return {@code true} if it is required
	 */
	public boolean isRequired() {
		return this.required;
	}

	/**
	 * Set whether this property is required
	 * @param flag The new value
	 */
	public void setRequired(final boolean flag) {
		this.required = flag;
	}

    /**
     * Get the optional default value.
     * @return The default value or {@code null}
     * @since 1.2
     */
    public Object getDefaultValue() {
        return this.defaultValue;
    }
    
    /**
     * Set the optional default value.
     * @param val The default value
     * @since 1.2
     */
    public void setDefaultValue(final Object val) {
        this.defaultValue = val;
    }

    /**
     * Get the validation mode.
     * @return The mode or {@code null}
     * @since 1.2
     */
    public Mode getMode() {
        return this.mode;
    }

    /**
     * Set the validation mode
     * @param value The validation mode
     * @since 1.2
     */
    public void setMode(final Mode value) {
        this.mode = value;
    }
 
    /**
     * Get the placeholder policy.
     * @return The policy
     * @since 1.3
     */
    public PlaceholderPolicy getPlaceholderPolicy() {
        return this.placeholderPolicy;
    }

    /**
     * Set the placeholder policy
     * @param policy The new policy
     * @since 1.3
     */
    public void setPlaceholderPolicy(final PlaceholderPolicy policy) {
        this.placeholderPolicy = policy == null ? PlaceholderPolicy.DEFAULT : policy;
    }

	/**
	 * Get the placeholder regex
	 * @return the placeholder regex or {@code null}
     * @since 1.3
	 */
    public String getPlaceholderRegex() {
        return placeholderPattern == null ? null : placeholderPattern.pattern();
    }

	/**
	 * Set the placeholder regex
	 * @param regex the placeholder regex to set
     * @throws IllegalArgumentException If the pattern is not valid
     * @since 1.3
	 */
    public void setPlaceholderRegex(final String regex) {
        if ( regex == null ) {
            this.placeholderPattern = null;
        } else {
            this.placeholderPattern = Pattern.compile(regex);
        }
    }

    /**
     * Get the placeholder regex pattern
     * @return The pattern or {@code null}
     * @since 1.3
     */
    public Pattern getPlaceholderRegexPattern() {
        return this.placeholderPattern;
    }
}
