/*
 * The Kuali Financial System, a comprehensive financial management system for higher education.
 *
 * Copyright 2005-2016 The Kuali Foundation
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.kuali.kfs.krad.datadictionary;

import org.kuali.kfs.krad.uif.UifConstants;
import org.kuali.kfs.krad.uif.UifConstants.ViewType;
import org.kuali.kfs.krad.uif.view.View;
import org.springframework.beans.PropertyValues;

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

/**
 * Maps one Document type to other document Type.
 * <p>
 * This interface can be used to implement KNS to workflow document type
 * mapping relationships other than one-to-one.
 */
public interface DataDictionaryMapper {
    /**
     * This method gets the business object entry for a concrete class
     *
     * @param className
     * @return
     */
    @Deprecated
    public BusinessObjectEntry getBusinessObjectEntryForConcreteClass(DataDictionaryIndex index, String className);

    /**
     * This method gets the DataOjectEntry (or subclass) for a concrete class
     *
     * @param className
     * @return the DataObjectEntry for the class or null if not found
     */
    public DataObjectEntry getDataObjectEntryForConcreteClass(DataDictionaryIndex index, String className);


    /**
     * @return List of businessObject classnames
     */
    @Deprecated
    public List<String> getBusinessObjectClassNames(DataDictionaryIndex index);

    /**
     * @param className
     * @return BusinessObjectEntry for the named class, or null if none exists
     */
    @Deprecated
    public BusinessObjectEntry getBusinessObjectEntry(DataDictionaryIndex index, String className);

    /**
     * @param className
     * @return DataObjectEntry for the named class, or null if none exists
     */
    public DataObjectEntry getDataObjectEntry(DataDictionaryIndex index, String className);

    /**
     * @return Map of (classname, BusinessObjectEntry) pairs
     */
    @Deprecated
    public Map<String, BusinessObjectEntry> getBusinessObjectEntries(DataDictionaryIndex index);

    /**
     * @param className
     * @return DataDictionaryEntryBase for the named class, or null if none
     * exists
     */
    public DataDictionaryEntry getDictionaryObjectEntry(DataDictionaryIndex index, String className);

    /**
     * Returns the KNS document entry for the given lookup key.  The documentTypeDDKey is interpreted
     * successively in the following ways until a mapping is found (or none if found):
     * <ol>
     * <li>KEW/workflow document type</li>
     * <li>business object class name</li>
     * <li>maintainable class name</li>
     * </ol>
     * This mapping is compiled when DataDictionary files are parsed on startup (or demand).  Currently this
     * means the mapping is static, and one-to-one (one KNS document maps directly to one and only
     * one key).
     *
     * @param documentTypeDDKey the KEW/workflow document type name
     * @return the KNS DocumentEntry if it exists
     */
    public DocumentEntry getDocumentEntry(DataDictionaryIndex index, String documentTypeDDKey);

    /**
     * Note: only MaintenanceDocuments are indexed by businessObject Class
     * <p>
     * This is a special case that is referenced in one location. Do we need
     * another map for this stuff??
     *
     * @param businessObjectClass
     * @return DocumentEntry associated with the given Class, or null if there
     * is none
     */
    public MaintenanceDocumentEntry getMaintenanceDocumentEntryForBusinessObjectClass(DataDictionaryIndex index, Class<?> businessObjectClass);

    public Map<String, DocumentEntry> getDocumentEntries(DataDictionaryIndex index);

    public Set<InactivationBlockingMetadata> getAllInactivationBlockingMetadatas(DataDictionaryIndex index, Class<?> blockedClass);

    /**
     * Returns mapped document type based on the given document type.
     *
     * @param documentType
     * @return new document type or null if given documentType was not found.
     */
    public String getDocumentTypeName(DataDictionaryIndex index, String documentTypeName);

    /**
     * Returns mapped document type class based on the given document type.
     *
     * @param documentType
     * @return the class of the mapped document type or null if given documentType was not found.
     */
    //public Class getDocumentTypeClass(String documentTypeName);

    /**
     * Returns the View entry identified by the given id
     *
     * @param index  - the view dictionary index
     * @param viewId - unique id for view
     * @return View instance associated with the id
     */
    public View getViewById(UifDictionaryIndex index, String viewId);

    /**
     * Called to retrieve a <code>View</code> instance that is of the given type
     * based on the index key
     *
     * @param index        - the view dictionary index
     * @param viewTypeName - type name for the view
     * @param indexKey     - Map of index key parameters, these are the parameters the
     *                     indexer used to index the view initially and needs to identify
     *                     an unique view instance
     * @return View instance that matches the given index
     */
    public View getViewByTypeIndex(UifDictionaryIndex index, ViewType viewTypeName, Map<String, String> indexKey);

    /**
     * Indicates whether a <code>View</code> exists for the given view type and index information
     *
     * @param index        - the view dictionary index
     * @param viewTypeName - type name for the view
     * @param indexKey     - Map of index key parameters, these are the parameters the
     *                     indexer used to index the view initially and needs to identify
     *                     an unique view instance
     * @return boolean true if view exists, false if not
     */
    public boolean viewByTypeExist(UifDictionaryIndex index, ViewType viewTypeName, Map<String, String> indexKey);

    /**
     * Gets all <code>View</code> prototypes configured for the given view type
     * name
     *
     * @param index        - the view dictionary index
     * @param viewTypeName - view type name to retrieve
     * @return List<View> view prototypes with the given type name, or empty
     * list
     */
    public List<View> getViewsForType(UifDictionaryIndex index, UifConstants.ViewType viewTypeName);

    /**
     * Retrieves the configured property values for the view bean definition associated with the given id
     * <p>
     * <p>
     * Since constructing the View object can be expensive, when metadata only is needed this method can be used
     * to retrieve the configured property values. Note this looks at the merged bean definition
     * </p>
     *
     * @param index  - the view dictionary index
     * @param viewId - id for the view to retrieve
     * @return PropertyValues configured on the view bean definition, or null if view is not found
     */
    public PropertyValues getViewPropertiesById(UifDictionaryIndex index, String viewId);

    /**
     * Retrieves the configured property values for the view bean definition associated with the given type and
     * index
     * <p>
     * <p>
     * Since constructing the View object can be expensive, when metadata only is needed this method can be used
     * to retrieve the configured property values. Note this looks at the merged bean definition
     * </p>
     *
     * @param index        - the view dictionary index
     * @param viewTypeName - type name for the view
     * @param indexKey     - Map of index key parameters, these are the parameters the indexer used to index
     *                     the view initially and needs to identify an unique view instance
     * @return PropertyValues configured on the view bean definition, or null if view is not found
     */
    public PropertyValues getViewPropertiesByType(UifDictionaryIndex index, UifConstants.ViewType viewTypeName,
                                                  Map<String, String> indexKey);

}
