/*-
 * ~~~~~~licensing~~~~~~
 * test-producers
 * ==========
 * Copyright (C) 2020 - 2022 EmDev LLC
 * ==========
 * Licensed 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.
 * ~~~~~~/licensing~~~~~~
 */
package ru.entaxy.platform.base.objects.factory;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.google.gson.JsonObject;

import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;

public interface EntaxyFactory extends EntaxyFactoryElements.EntaxyFactoryExtendedElement {

	/*
	 * public constants, enums etc
	 */
	
	public static interface SERVICE {

		String PROP_ID = "factory.id";
		String PROP_TYPE = "factory.type";
		String PROP_ORIGIN_BUNDLE = "factory.origin.bundle";
		
	}

	public static interface CONFIGURATION {

		String FACTORY_SECTION_NAME = "factory";
		String FIELDS_SECTION_NAME = "fields";
		String OUTPUTS_SECTION_NAME = "outputs";
		
		public static interface FACTORY {
			
			String ID = "id";
			String TYPE = "type";
			String DESCRIPTION = "description";
			String LABEL = "label";
			String CATEGORY = "category";
			
		}
		
		public static interface FIELDS {
			
			public static interface REGULAR_TYPES {
				
				String STRING = "String";
				String BOOLEAN = "Boolean";
				String LONG = "Long";
				String DOUBLE = "Double";
				
				public static Set<String> asSet() {
					return new HashSet<>() {{
						add(STRING);
						add(BOOLEAN);
						add(DOUBLE);
						add(LONG);
					}};
				}
				
			}
			
			public static interface ATTRIBUTES {
				
				String FIELD_TYPE = "type";
				String DEFAULT_VALUE = "defaultValue";
				
				String REQUIRED = "required";
				String IMMUTABLE = "immutable";
				
				String IS_REF = "isRef";
				
			}
			
			String OBJECT_ID = "objectId";
			
		}
		
		public static interface OUTPUTS {

			String OUTPUT_TYPE_INIT = "init";
			String OUTPUT_TYPE_REF = "ref";
			
			public static interface ATTRIBUTES {
			
				String IS_DEFAULT = "isDefault";
				String CONFIG = "config";
				String GENERATOR = "generator";
				String FIELDS = "fields";
				String SCOPES = "scopes";
				
			}
		}
		
	}
	
	
	static public enum SCOPE {
		PUBLIC("public"),
		PROTECTED("protected"),
		PRIVATE("private");
		
	    public String label;

	    private SCOPE(String label) {
	        this.label = label;
	    }
	    
	    public static SCOPE valueOfLabel(String label) {
	        for (SCOPE e : values()) {
	            if (e.label.equals(label)) {
	                return e;
	            }
	        }
	        return null;
	    }	    
	}
	
	static public SCOPE DEFAULT_SCOPE = SCOPE.PUBLIC;
	
	/*
	 * inner structure elements
	 */
	
	public static interface OutputInfo {
		
		public String getType();
		public String getGenerator();
		public List<String> getScopes();
		public Map<String, Object> getConfig();
		public List<FieldInfo> getFields();
		public boolean isDefault();
		
	}

	public static interface FieldInfo {
		
		public String getName();
		public String getType();
		public String getDisplayName();
		public String getDescription();

		public boolean isImmutable();
		public boolean isRequired();
		public Object getDefaultValue();

		public boolean isConditional();
		public String getCondition();
		
		public boolean isRef();
		public JsonObject getJsonOrigin();
		
	}

	public static interface RefFieldInfo extends FieldInfo {
		
		public boolean isBackRef();
		public boolean isRefByValueOnly();
		
		public String getRefField();
		
	}
	
	/*
	 * Factory itself
	 */

	@Deprecated()
	public default String getFactoryId() {
		return getId();
	};
	@Deprecated
	public default String getFactoryType() {
		return getType();
	};
	
	
	public List<OutputInfo> getOutputs();
	public OutputInfo getDefaultOutput();
	public OutputInfo getOutputByType(String outputType);
	
	public List<FieldInfo> getFields();
	public List<FieldInfo> getFields(String outputType);
	
	public Generated generate(Map<String, Object> parameters) throws EntaxyFactoryException ;
	public Generated generate(String outputType, Map<String, Object> parameters) throws EntaxyFactoryException;
	public Generated generate(String outputType, String scope, Map<String, Object> parameters) throws EntaxyFactoryException;
	
}
