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

import java.io.IOException;
import java.util.Collection;
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 javolution.util.FastList;
import javolution.util.FastMap;
import javolution.util.FastSet;

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.GeneralException;
import org.ofbiz.base.util.UtilGenerics;
import org.ofbiz.content.data.DataResourceWorker;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.util.EntityQuery;
import org.ofbiz.service.LocalDispatcher;
import org.ofbiz.webapp.control.RequestHandler;
import org.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 = FastSet.newInstance();
    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() {
        // Debug.logWarning("This method [keySet()] is not completely implemented in ContentMapFacade", module);
        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)
                                .cache().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);
                // Debug.logInfo("Made link to content with ID [" + this.contentId + "]: " + contextLink, module);
                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 = FastList.newInstance();
            List<GenericValue> subs = null;
            try {
                Map<String, Object> expressions = FastMap.newInstance();
                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 = FastMap.newInstance();
        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 = FastMap.newInstance();
                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;
        }
    }
}
