package com.libreecm.commonAPI.model;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.libreecm.commonAPI.model.enums.*;
import com.libreecm.commonAPI.model.objects.ObjectType;
import com.libreecm.commonAPI.model.objects.Uri;

/**
 * 
 * This class defines a Repository and all it's attributes Id: is an INTEGER
 * that refers the object persistence Path: is a URI:
 * Type://Name/baseFolder/secondFolder/.../parentFolder/repositoryRoot/ - Type
 * defines the repository Type - Name defines so it could difference between
 * same type repositories NAME SHOUD BE UNIQUE AT THE DDBB - Folders tree -
 * Object is always ""
 * 
 * This class stores all information that is not persisted at the FS or DB where
 * documents are
 * 
 * @author Jordi Pérez Bayerri
 */
public class Repository extends LibreECMObject {
	/**
	 * 
	 */
	private static final long serialVersionUID = -3719876864024503895L;
	private boolean accessible;
	private AclCapabilities aclCapabilities;
	private boolean active;
	protected List<ObjectType> allowedObjectTypeId = new ArrayList<>();

	/**
	 * Boolean showing there is tasks pending (work in progress)
	 */
	private Boolean changesIncomplete;

	/**
	 * A collection of types changed by this repository
	 */
	private List<BaseTypeId> changesOnType;

	/**
	 * A collection of additional cmis extension elements supported by this
	 * repository
	 */
	private List<CmisExtensionElement> cmisExtensionElements;

	private CmisVersion cmisVersion;

	private String cmisVersionSupported;

	/**
	 * An array of Id for customized types supporting at this repository
	 */
	private List<String> customizedTypes = new ArrayList<String>();

	private String description;

	/**
	 * A collection of additional features supported by this repository
	 */
	private List<ExtensionFeature> extensionFeatures;

	private Integer id;
	/**
	 * Token for last change LOG
	 */
	private String latestChangeLogToken;

	private String name;

	/**
	 * Path where the table for a DB or root of a fs of this repository
	 */
	private String path;

	/**
	 * Main Id
	 */
	private String principalIdAnonymous;

	/**
	 * Main Id
	 */
	private String principalIdAnyone;

	/**
	 * Comercial Name of the repository product
	 */
	private String productName;

	/**
	 * Comercial version of the repository product
	 */
	private String productVersion;

	private RepositoryCapabilities repositoryCapabilities;

	/**
	 * Id of the repository's root folder
	 */
	private String rootFolderId;

	/**
	 * Where to locate fisically the repository
	 */
	private String thinClientUri;
	/**
	 * Sets an existing repository Type. It has to exist or an exception is
	 * thrown. Ex. FSRepository, DDBBRepository....
	 */
	private String typeId;

	/**
	 * Vendor of the repository
	 */
	private String vendorName;

	public Repository() {
		this.principalIdAnonymous = "";
		this.aclCapabilities = new AclCapabilities();
		this.changesIncomplete = false;
		this.changesOnType = new ArrayList<>();
		this.cmisExtensionElements = new ArrayList<>();
		this.cmisVersion = CmisVersion.CMIS_1_1;
		this.cmisVersionSupported = CmisVersion.CMIS_1_1.value();
		this.customizedTypes = new ArrayList<>();
		this.description = "";
		this.extensionFeatures = new ArrayList<>();
		this.latestChangeLogToken = "";
		this.name = "";
		this.principalIdAnyone = "";
		this.productName = "";
		this.productVersion = "";
		this.repositoryCapabilities = new RepositoryCapabilities();
		this.rootFolderId = "";
		this.thinClientUri = "";
		this.vendorName = "";
		this.id = 0;
	}

	public Repository(String id, String name, String description, String rootFolderId, String principalIdAnonymous,
			String principalIdAnyone, String thinClientUri, Boolean changesIncomplete, String latestChangeLogToken,
			String vendorName, String productName, String productVersion, AclCapabilities capabilitiesAcl,
			RepositoryCapabilities repositoryCapabilities, String cmisVersionSupported, CmisVersion cmisVersion,
			List<String> customizedTypes, List<ExtensionFeature> extensionFeatures, List<BaseTypeId> changesOnType,
			List<CmisExtensionElement> cmisExtensionElements) {
		super();
		this.id = Integer.parseInt(id);
		this.name = name;
		this.description = description;
		this.rootFolderId = rootFolderId;
		this.principalIdAnonymous = principalIdAnonymous;
		this.principalIdAnyone = principalIdAnyone;
		this.thinClientUri = thinClientUri;
		this.changesIncomplete = changesIncomplete;
		this.latestChangeLogToken = latestChangeLogToken;
		this.vendorName = vendorName;
		this.productName = productName;
		this.productVersion = productVersion;
		this.aclCapabilities = capabilitiesAcl;
		this.repositoryCapabilities = repositoryCapabilities;
		this.cmisVersionSupported = cmisVersionSupported;
		this.cmisVersion = cmisVersion;
		this.customizedTypes = customizedTypes;
		this.extensionFeatures = extensionFeatures;
		this.changesOnType = changesOnType;
		this.cmisExtensionElements = cmisExtensionElements;

		this.id = 0;
	}

	public Repository(Uri uri) {
		this.principalIdAnonymous = "";
		this.aclCapabilities = new AclCapabilities();
		this.changesIncomplete = false;
		this.changesOnType = new ArrayList<>();
		this.cmisExtensionElements = new ArrayList<>();
		this.cmisVersion = CmisVersion.CMIS_1_1;
		this.cmisVersionSupported = CmisVersion.CMIS_1_1.value();
		this.customizedTypes = new ArrayList<>();
		this.description = "";
		this.extensionFeatures = new ArrayList<>();
		this.latestChangeLogToken = "";
		this.name = "";
		this.principalIdAnyone = "";
		this.productName = "";
		this.productVersion = "";
		this.repositoryCapabilities = new RepositoryCapabilities();
		this.thinClientUri = "";
		this.vendorName = "";
		this.id = 0;
		this.setName(uri.getRepositoryName());
		this.setPath(uri.getFolderTree());
		this.setTypeId(uri.getType());
		Uri rootFolderUri= new Uri();
		rootFolderUri.setObject("");
		rootFolderUri.setRepositoryName(this.getName());
		rootFolderUri.setType(BaseTypeId.CMIS_FOLDER.value());
		rootFolderUri.setFolderTree(new ArrayList<String>());
		this.rootFolderId = rootFolderUri.toString();
	}

	public AclCapabilities getAclCapabilities() {
		if (this.aclCapabilities == null) {
			this.aclCapabilities = new AclCapabilities();
		}
		return aclCapabilities;
	}

	/**
	 * @return the allowedObjectTypeId
	 */
	public List<ObjectType> getAllowedObjectTypeId() {
		return allowedObjectTypeId;
	}

	public Boolean getChangesIncomplete() {
		return changesIncomplete;
	}

	public List<BaseTypeId> getChangesOnType() {
		if (this.changesOnType == null) {
			this.changesOnType = new ArrayList<BaseTypeId>();
		}
		return changesOnType;
	}

	public List<CmisExtensionElement> getCmisExtensionElements() {
		if (this.cmisExtensionElements == null) {
			this.cmisExtensionElements = new ArrayList<>();
		}
		return this.cmisExtensionElements;
	}

	public CmisVersion getCmisVersion() {
		return cmisVersion;
	}

	public String getCmisVersionSupported() {
		return this.cmisVersionSupported;
	}

	public List<String> getCustomizedTypes() {
		return customizedTypes;
	}

	public String getDescription() {
		return description;
	}

	public List<ExtensionFeature> getExtensionFeatures() {
		ArrayList<ExtensionFeature> array = new ArrayList<>();
		array.addAll(this.extensionFeatures);
		return array;
	}

	public String getId() {
		if (id == null) {
			return null;
		}
		return this.id.toString();
	}

	public String getLatestChangeLogToken() {
		return latestChangeLogToken;
	}

	public String getName() {
		return name;
	}

	/**
	 * return Path where the table for a DB or root of a fs of this repository
	 * Example: making File(getPath()) works and return a folder
	 */
	public String getPath() {
		return path;
	}

	public String getPrincipalIdAnonymous() {
		return this.principalIdAnonymous.toString();
	}

	public String getPrincipalIdAnyone() {
		return this.principalIdAnyone.toString();
	}

	public String getProductName() {
		return productName;
	}

	public String getProductVersion() {
		return productVersion;
	}

	public RepositoryCapabilities getRepositoryCapabilities() {
		return repositoryCapabilities;
	}

	public String getRootFolderId() {
		return this.rootFolderId;
	}

	public String getThinClientUri() {
		return thinClientUri;
	}

	/**
	 * @return the typeId
	 */
	public String getTypeId() {
		return typeId;
	}

	public String getVendorName() {
		return vendorName;
	}

	/**
	 * @return the accessible
	 */
	public boolean isAccessible() {
		return accessible;
	}

	/**
	 * @return the active
	 */
	public boolean isActive() {
		return active;
	}

	/**
	 * @param accessible
	 *            the accessible to set
	 */
	public void setAccessible(boolean accessible) {
		this.accessible = accessible;
	}

	public void setAclCapabilities(AclCapabilities capabilitiesAcl) {
		if (capabilitiesAcl == null) {
			this.aclCapabilities = new AclCapabilities();
		}
		this.aclCapabilities = capabilitiesAcl;
	}

	/**
	 * @param active
	 *            the active to set
	 */
	public void setActive(boolean active) {
		this.active = active;
	}

	/**
	 * @param allowedObjectTypeId
	 *            the allowedObjectTypeId to set
	 */
	public void setAllowedObjectTypeId(List<ObjectType> allowedObjectTypeId) {
		this.allowedObjectTypeId = allowedObjectTypeId;
	}

	public void setChangesIncomplete(Boolean changesIncomplete) {
		this.changesIncomplete = changesIncomplete;
	}

	public void setChangesOnType(List<BaseTypeId> changesOnType) {
		this.changesOnType = changesOnType;
	}

	public void setCmisExtensionElements(List<CmisExtensionElement> arg0) {
		this.cmisExtensionElements = arg0;
	}

	public void setCmisVersion(CmisVersion cmisVersion) {
		this.cmisVersion = cmisVersion;
	}

	public void setCmisVersionSupported(String cmisVersionSupported) {
		this.cmisVersionSupported = cmisVersionSupported;
	}

	public void setCustomizedTypes(List<String> customizedTypes) {
		this.customizedTypes = customizedTypes;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public void setExtensionFeatures(List<ExtensionFeature> extensions) {
		if (extensions != null) {
			this.extensionFeatures = new ArrayList<ExtensionFeature>();
			Iterator<ExtensionFeature> it = extensions.iterator();
			while (it.hasNext()) {
				this.extensionFeatures.add((ExtensionFeature) it.next());
			}
		}
	}

	public void setId(String id) {
		this.id = Integer.parseInt(id);
	}

	public void setLatestChangeLogToken(String latestChangeLogToken) {
		this.latestChangeLogToken = latestChangeLogToken;
	}

	public void setName(String name) {
		this.name = name;
	}

	/**
	 * Sets some basic location properties: Sets the repository type Sets the
	 * repository name Sets the object always to "" Sets the repository folder
	 * tree location, for example if FS: At unix, folder tree could be
	 * /media/repositories/repository1 At windows, folder tree could be
	 * D:\repositories\repository1, so D: is treatted as a folder For DB
	 * systems: Folder tree will have two elements, DB name and Table name
	 * 
	 * @param path
	 *            the path to set
	 */
	public void setPath(String path) {
		this.path = path;
	}

	public void setPrincipalIdAnonymous(String id) {
		this.principalIdAnonymous = id;
	}

	public void setPrincipalIdAnyone(String principalIdAnyone) {
		this.principalIdAnyone = principalIdAnyone;
	}

	public void setProductName(String productName) {
		this.productName = productName;
	}

	public void setProductVersion(String productVersion) {
		this.productVersion = productVersion;
	}

	public void setRepositoryCapabilities(RepositoryCapabilities repositoryCapabilities) {
		this.repositoryCapabilities = repositoryCapabilities;
	}

	public void setRootFolderId(String id) {
		this.rootFolderId = id;
	}

	public void setThinClientUri(String thinClientUri) {
		this.thinClientUri = thinClientUri;
	}

	/**
	 * @param typeId
	 *            the typeId to set
	 */
	public void setTypeId(String typeId) {
		this.typeId = typeId;
	}

	public void setVendorName(String vendorName) {
		this.vendorName = vendorName;
	}

	public String toString() {
		return "Repository id:" + getId() + " name " + getName() + " description " + getDescription();
	}

}