/*
k 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.ofbiz.content.content;

import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.GeneralException;
import org.apache.ofbiz.base.util.UtilGenerics;
import org.apache.ofbiz.content.data.DataResourceWorker;
import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.GenericEntityException;
import org.apache.ofbiz.entity.GenericValue;
import org.apache.ofbiz.entity.util.EntityQuery;
import org.apache.ofbiz.service.LocalDispatcher;
import org.apache.ofbiz.webapp.control.RequestHandler;
import org.apache.ofbiz.webapp.website.WebSiteWorker;

/**
 * ContentMapFacade
 */
public class ContentMapFacade implements Map<Object, Object> {

    public static final String module = ContentMapFacade.class.getName();

    protected static final Set<String> mapKeySet = new HashSet<String>();
    static {
        mapKeySet.add("fields");
        mapKeySet.add("link");
        mapKeySet.add("data");
        mapKeySet.add("dataresource");
        mapKeySet.add("subcontent");
        mapKeySet.add("subcontent_all");
        mapKeySet.add("metadata");
        mapKeySet.add("content");
        mapKeySet.add("render");
    }

    protected final LocalDispatcher dispatcher;
    protected final Delegator delegator;
    protected final String contentId;
    protected final GenericValue value;
    protected final Map<String, Object> context;
    protected final Locale locale;
    protected final String mimeType;
    protected final boolean cache;
    protected boolean allowRender = true;
    protected boolean isDecorated = false;
    protected ContentMapFacade decoratedContent = null;

    // internal objects
    private String sortOrder="-fromDate";
    private String mapKeyFilter="";
    private String statusFilter="";
    private DataResource dataResource;
    private SubContent subContent;
    private MetaData metaData;
    private Content content;
    private GenericValue fields = null;

    public ContentMapFacade(LocalDispatcher dispatcher, GenericValue content, Map<String, Object> context, Locale locale, String mimeTypeId, boolean cache) {
        this.dispatcher = dispatcher;
        this.value = content;
        this.context = context;
        this.locale = locale;
        this.mimeType = mimeTypeId;
        this.cache = cache;
        this.contentId = content.getString("contentId");
        this.delegator = content.getDelegator();
        this.allowRender = false;
        init();
    }

    private ContentMapFacade(LocalDispatcher dispatcher, Delegator delegator, String contentId, Map<String, Object> context, Locale locale, String mimeTypeId, boolean cache) {
        this.dispatcher = dispatcher;
        this.delegator = delegator;
        this.contentId = contentId;
        this.context = context;
        this.locale = locale;
        this.mimeType = mimeTypeId;
        this.cache = cache;
        try {
            if (cache) {
                this.value = EntityQuery.use(delegator).from("Content").where("contentId", contentId).cache().queryOne();
            } else {
                this.value = EntityQuery.use(delegator).from("Content").where("contentId", contentId).queryOne();
            }
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            throw new RuntimeException(e.getMessage());
        }
        init();
    }

    private void init() {
        this.dataResource = new DataResource();
        this.subContent = new SubContent();
        this.metaData = new MetaData();
        this.content = new Content();
    }

    public void setRenderFlag(boolean render) {
        this.allowRender = render;
    }

    public void setIsDecorated(boolean isDecorated) {
        this.isDecorated = isDecorated;
    }

    // interface methods
    public int size() {
        return 1;
    }

    public boolean isEmpty() {
        return false;
    }

    public boolean containsKey(Object object) {
        return false;
    }

    public boolean containsValue(Object object) {
        return false;
    }

    public Object put(Object name, Object value) {
        Debug.logWarning("This [put()] method is not implemented in ContentMapFacade", module);
        return null;
    }

    public Object remove(Object object) {
        Debug.logWarning("This [remove()] method is not implemented in ContentMapFacade", module);
        return null;
    }

    public void putAll(Map<?, ?> map) {
        Debug.logWarning("This method [putAll()] is not implemented in ContentMapFacade", module);
    }

    public void clear() {
        Debug.logWarning("This method [clear()] is not implemented in ContentMapFacade", module);
    }

    public Set<Object> keySet() {
        return UtilGenerics.checkSet(mapKeySet);
    }

    public Collection<Object> values() {
        Debug.logWarning("This method [values()] is not implemented in ContentMapFacade", module);
        return null;
    }

    public Set<Map.Entry<Object, Object>> entrySet() {
        Debug.logWarning("This method [entrySet()] is not implemented in ContentMapFacade", module);
        return null;
    }

    public void setSortOrder(Object obj) {
        if (!(obj instanceof String)) {
            Debug.logWarning("sortOrder parameters must be a string", module);
            return;
        }
        this.sortOrder=(String) obj;
        this.subContent.setSortOrder(obj);
    }

    public void setMapKeyFilter(Object obj) {
        if (!(obj instanceof String)) {
            Debug.logWarning("mapKeyFilter parameters must be a string", module);
            return;
        }
        this.mapKeyFilter=(String) obj;
    }

    public void setStatusFilter(Object obj) {
        if (!(obj instanceof String)) {
            Debug.logWarning("statusFilter parameters must be a string", module);
            return;
        }
        this.statusFilter=(String) obj;
        this.subContent.setStatusFilter(obj);
    }

    public void setDecoratedContent(ContentMapFacade decoratedContent) {
        this.decoratedContent = decoratedContent;
    }

    // implemented get method
    public Object get(Object obj) {
        if (!(obj instanceof String)) {
            Debug.logWarning("Key parameters must be a string", module);
            return null;
        }
        String name = (String) obj;

        if ("fields".equalsIgnoreCase(name)) {
            // fields key, returns value object
            if (this.fields != null) {
                return fields;
            }
            try {
                EntityQuery contentQuery = EntityQuery.use(delegator).from("Content").where("contentId", contentId);
                if (cache) {
                    contentQuery.cache();
                }
                this.fields = contentQuery.queryOne();
            } catch (GenericEntityException e) {
                Debug.logError(e, module);
            }
            return this.fields;

        } else if ("link".equalsIgnoreCase(name)) {
            // link to this content

            RequestHandler rh = (RequestHandler) this.context.get("_REQUEST_HANDLER_");
            HttpServletRequest request = (HttpServletRequest) this.context.get("request");
            HttpServletResponse response = (HttpServletResponse) this.context.get("response");

            if (rh != null && request != null && response != null) {
                String webSiteId = WebSiteWorker.getWebSiteId(request);
                Delegator delegator = (Delegator) request.getAttribute("delegator");
                
                String contentUri = this.contentId;
                // Try and find a WebSitePathAlias record to use, it isn't very feasible to find an alias by (parent)contentId/mapKey
                // so we're only looking for a direct alias using contentId
                if (webSiteId != null && delegator != null) {
                    try {
                    	
                        GenericValue webSitePathAlias = EntityQuery.use(delegator).from("WebSitePathAlias")
                                .where("mapKey", null,
                                        "webSiteId", webSiteId,
                                        "contentId", this.contentId)
                                .orderBy("-fromDate")
                                .cache().filterByDate().queryFirst();
                        if (webSitePathAlias != null) {
                            contentUri = webSitePathAlias.getString("pathAlias");
                        }
                    } catch (GenericEntityException e) {
                        Debug.logError(e, module);
                    }
                }
                String contextLink = rh.makeLink(request, response, contentUri, true, false, true);
                return contextLink;
            } else {
                return this.contentId;
            }
        } else if ("data".equalsIgnoreCase(name) || "dataresource".equalsIgnoreCase(name)) {
            // data (resource) object
            return dataResource;
        } else if ("subcontent_all".equalsIgnoreCase(name)) {
            // subcontent list of ordered subcontent
            List<ContentMapFacade> subContent = new LinkedList<ContentMapFacade>();
            List<GenericValue> subs = null;
            try {
                Map<String, Object> expressions = new HashMap<String, Object>();
                expressions.put("contentIdStart", contentId);
                if(!this.mapKeyFilter.equals("")) {
                    expressions.put("caMapKey", this.mapKeyFilter);
                }
                if(!this.statusFilter.equals("")) {
                    expressions.put("statusId", this.statusFilter);
                }

                subs = EntityQuery.use(delegator).from("ContentAssocViewTo")
                        .where(expressions)
                        .orderBy(this.sortOrder)
                        .filterByDate()
                        .cache(cache).queryList();
            } catch (GenericEntityException e) {
                Debug.logError(e, module);
            }
            if (subs != null) {
                for (GenericValue v: subs) {
                    subContent.add(new ContentMapFacade(dispatcher, delegator, v.getString("contentId"), context, locale, mimeType, cache));
                }
            }
            return subContent;
        } else if ("subcontent".equalsIgnoreCase(name)) {
            // return the subcontent object
            return this.subContent;
        } else if ("metadata".equalsIgnoreCase(name)) {
            // return list of metaData by predicate ID
            return this.metaData;
        } else if ("content".equalsIgnoreCase(name)) {
            // content; returns object from contentId
            return content;
        } else if ("render".equalsIgnoreCase(name)) {
            // render this content
            return this.renderThis();
        }

        return null;
    }

    protected String renderThis() {
        if (!this.allowRender && !this.isDecorated) {
            String errorMsg = "WARNING: Cannot render content being rendered! (Infinite Recursion NOT allowed!)";
            Debug.logWarning(errorMsg, module);
            return "=========> " + errorMsg + " <=========";
        }
        // TODO: change to use the MapStack instead of a cloned Map
        Map<String, Object> renderCtx = new HashMap<String, Object>();
        renderCtx.putAll(context);
        if (this.decoratedContent != null) {
            renderCtx.put("decoratedContent", decoratedContent);
        }

        if (this.isDecorated) {
            renderCtx.put("_IS_DECORATED_", Boolean.TRUE);
        }

        try {
            return ContentWorker.renderContentAsText(dispatcher, delegator, contentId, renderCtx, locale, mimeType, cache);
        } catch (GeneralException e) {
            Debug.logError(e, module);
            return e.toString();
        } catch (IOException e) {
            Debug.logError(e, module);
            return e.toString();
        }
    }

    @Override
    public String toString() {
        return this.renderThis();
    }

    abstract class AbstractInfo implements Map<Object, Object> {
        public int size() {
            return 1;
        }

        public boolean isEmpty() {
            return false;
        }

        public boolean containsKey(Object object) {
            return false;
        }

        public boolean containsValue(Object object) {
            return false;
        }

        public abstract Object get(Object object);


        public Object put(Object name, Object value) {
            Debug.logWarning("This [put()] method is not implemented in ContentMapFacade.AbstractInfo", module);
            return null;
        }

        public Object remove(Object object) {
            Debug.logWarning("This [remove()] method is not implemented in ContentMapFacade.AbstractInfo", module);
            return null;
        }

        public void putAll(Map<?, ?> map) {
            Debug.logWarning("This method [putAll()] is not implemented in ContentMapFacade.AbstractInfo", module);
        }

        public void clear() {
            Debug.logWarning("This method [clear()] is not implemented in ContentMapFacade.AbstractInfo", module);
        }

        public Set<Object> keySet() {
            Debug.logWarning("This method [keySet()] is not implemented in ContentMapFacade.AbstractInfo", module);
            return null;
        }

        public Collection<Object> values() {
            Debug.logWarning("This method [values()] is not implemented in ContentMapFacade.AbstractInfo", module);
            return null;
        }

        public Set<Map.Entry<Object, Object>> entrySet() {
            Debug.logWarning("This method [entrySet()] is not implemented in ContentMapFacade.AbstractInfo", module);
            return null;
        }
    }

    class Content extends AbstractInfo {
        @Override
        public Object get(Object key) {
            if (!(key instanceof String)) {
                Debug.logWarning("Key parameters must be a string", module);
                return null;
            }
            String name = (String) key;
            if (name.toLowerCase().startsWith("id_")) {
                name = name.substring(3);
            }

            // look up the content ID (of name)
            GenericValue content = null;
            try {
                if (cache) {
                    content = EntityQuery.use(delegator).from("Content").where("contentId", name).cache().queryOne();
                } else {
                    content = EntityQuery.use(delegator).from("Content").where("contentId", name).queryOne();
                }
            } catch (GenericEntityException e) {
                Debug.logError(e, module);
            }
            if (content != null) {
                return new ContentMapFacade(dispatcher, delegator, content.getString("contentId"), context, locale, mimeType, cache);
            }

            return null;
        }
    }

    class SubContent extends AbstractInfo {
        private String sortOrder="-fromDate";
        private String statusFilter="";
        @Override
        public Object get(Object key) {
            if (!(key instanceof String)) {
                Debug.logWarning("Key parameters must be a string", module);
                return null;
            }
            String name = (String) key;
            if (name.toLowerCase().startsWith("id_")) {
                name = name.substring(3);
            }

            // key is the mapKey
            GenericValue sub = null;
            try {
                Map<String, Object> expressions = new HashMap<String, Object>();
                expressions.put("contentIdStart", contentId);
                expressions.put("caMapKey", name);
                if(!this.statusFilter.equals("")) {
                    expressions.put("statusId", this.statusFilter);
                }
                sub = EntityQuery.use(delegator).from("ContentAssocViewTo")
                        .where(expressions)
                        .orderBy(this.sortOrder)
                        .cache(cache)
                        .filterByDate().queryFirst();
            } catch (GenericEntityException e) {
                Debug.logError(e, module);
            }
            if (sub != null) {
                return new ContentMapFacade(dispatcher, delegator, sub.getString("contentId"), context, locale, mimeType, cache);
            }

            return null;
        }
        public void setSortOrder(Object obj) {
            if (!(obj instanceof String)) {
                Debug.logWarning("sortOrder parameters must be a string", module);
                return;
            }
            this.sortOrder=(String) obj;
        }
        public void setStatusFilter(Object obj) {
            if (!(obj instanceof String)) {
                Debug.logWarning("statusFilter parameters must be a string", module);
                return;
            }
            this.statusFilter=(String) obj;
        }
    }

    class MetaData extends AbstractInfo {
        @Override
        public Object get(Object key) {
            if (!(key instanceof String)) {
                Debug.logWarning("Key parameters must be a string", module);
                return null;
            }
            String name = (String) key;
            List<GenericValue> metaData = null;
            try {
                metaData = EntityQuery.use(delegator).from("ContentMetaData")
                        .where("contentId", contentId, "metaDataPredicateId", name)
                        .cache(cache).queryList();
            } catch (GenericEntityException e) {
                Debug.logError(e, module);
            }
            return metaData;
        }
    }

    class DataResource extends AbstractInfo {
        @Override
        public Object get(Object key) {
            if (!(key instanceof String)) {
                Debug.logWarning("Key parameters must be a string", module);
                return null;
            }
            String name = (String) key;

            if ("fields".equalsIgnoreCase(name)) {
                // get the data resource value object
                GenericValue dr = null;
                try {
                    dr = value.getRelatedOne("DataResource", cache);
                } catch (GenericEntityException e) {
                    Debug.logError(e, module);
                }
                return dr;
            } else if ("render".equalsIgnoreCase(name)) {
                // render just the dataresource
                try {
                    return DataResourceWorker.renderDataResourceAsText(delegator, value.getString("dataResourceId"), context, locale, mimeType, cache);
                } catch (GeneralException e) {
                    Debug.logError(e, module);
                    return e.toString();
                } catch (IOException e) {
                    Debug.logError(e, module);
                    return e.toString();
                }
            }

            return null;
        }
    }
}
