/*
 * 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.lenya.cms.repository;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.lenya.cms.cocoon.source.SourceUtil;
import org.apache.lenya.cms.metadata.ElementSet;
import org.apache.lenya.cms.metadata.MetaData;
import org.apache.lenya.cms.metadata.MetaDataException;
import org.apache.lenya.cms.metadata.MetaDataOwner;
import org.apache.lenya.cms.metadata.MetaDataRegistry;
import org.apache.lenya.cms.metadata.dublincore.DublinCore;
import org.apache.lenya.cms.publication.PageEnvelope;
import org.apache.lenya.xml.DocumentHelper;
import org.apache.lenya.xml.NamespaceHelper;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * Handles the meta data of source nodes.
 */
public class SourceNodeMetaDataHandler implements MetaDataOwner {

    private ServiceManager manager;
    private String sourceUri;

    /**
     * @param manager The service manager.
     * @param sourceUri The soure URI.
     */
    public SourceNodeMetaDataHandler(ServiceManager manager, String sourceUri) {
        this.manager = manager;
        this.sourceUri = sourceUri;
    }

    private Map namespace2metadata = new HashMap();

    public MetaData getMetaData(String namespaceUri) throws MetaDataException {

        MetaData meta = (MetaData) this.namespace2metadata.get(namespaceUri);
        if (meta == null) {
            
            MetaDataRegistry registry = null;
            try {
                registry = (MetaDataRegistry) this.manager.lookup(MetaDataRegistry.ROLE);
                if (!registry.isRegistered(namespaceUri)) {
                    throw new MetaDataException("The namespace [" + namespaceUri
                            + "] is not registered!");
                }
            } catch (ServiceException e) {
                throw new MetaDataException(e);
            } finally {
                if (registry != null) {
                    this.manager.release(registry);
                }
            }
            
            synchronized (this) {
                meta = new SourceNodeMetaData(namespaceUri, this, this.manager);
                this.namespace2metadata.put(namespaceUri, meta);
            }
        }
        return meta;
    }

    protected Map namespace2metamap = null;

    protected synchronized Map getMetaDataMap(String namespaceUri) throws MetaDataException {
        if (this.namespace2metamap == null) {
            loadMetaData();
        }
        Map map = (Map) this.namespace2metamap.get(namespaceUri);
        if (map == null) {
            map = new HashMap();
            this.namespace2metamap.put(namespaceUri, map);
        }
        return map;
    }

    protected static final String META_DATA_NAMESPACE = "http://apache.org/lenya/metadata/1.0";
    protected static final String ELEMENT_METADATA = "metadata";
    protected static final String ELEMENT_SET = "element-set";
    protected static final String ELEMENT_ELEMENT = "element";
    protected static final String ELEMENT_VALUE = "value";
    protected static final String ATTRIBUTE_NAMESPACE = "namespace";
    protected static final String ATTRIBUTE_KEY = "key";

    protected synchronized void loadMetaData() throws MetaDataException {

        if (this.namespace2metamap != null) {
            throw new IllegalStateException("The meta data have already been loaded!");
        }

        try {
            this.namespace2metamap = new HashMap();
            if (SourceUtil.exists(this.sourceUri, this.manager)) {
                Document xml = SourceUtil.readDOM(this.sourceUri, this.manager);
                if (!xml.getDocumentElement().getNamespaceURI().equals(META_DATA_NAMESPACE)) {
                    loadLegacyMetaData(xml);
                } else {
                    NamespaceHelper helper = new NamespaceHelper(META_DATA_NAMESPACE, "", xml);
                    Element[] setElements = helper.getChildren(xml.getDocumentElement(),
                            ELEMENT_SET);
                    for (int setIndex = 0; setIndex < setElements.length; setIndex++) {
                        String namespace = setElements[setIndex].getAttribute(ATTRIBUTE_NAMESPACE);
                        Element[] elementElements = helper.getChildren(setElements[setIndex],
                                ELEMENT_ELEMENT);
                        Map element2values = new HashMap();
                        for (int elemIndex = 0; elemIndex < elementElements.length; elemIndex++) {
                            String key = elementElements[elemIndex].getAttribute(ATTRIBUTE_KEY);
                            Element[] valueElements = helper.getChildren(
                                    elementElements[elemIndex], ELEMENT_VALUE);
                            List values = new ArrayList();
                            for (int valueIndex = 0; valueIndex < valueElements.length; valueIndex++) {
                                String value = DocumentHelper
                                        .getSimpleElementText(valueElements[valueIndex]);
                                values.add(value);
                            }
                            element2values.put(key, values);
                        }
                        this.namespace2metamap.put(namespace, element2values);
                    }
                }
            }
        } catch (Exception e) {
            throw new MetaDataException(e);
        }
    }

    protected void loadLegacyMetaData(Document xml) throws MetaDataException {
        NamespaceHelper helper = new NamespaceHelper(PageEnvelope.NAMESPACE, "", xml);

        Element metaElement = helper.getFirstChild(xml.getDocumentElement(), "meta");

        Element internalElement = helper.getFirstChild(metaElement, "internal");

        Element[] internalElements = helper.getChildren(internalElement);
        for (int i = 0; i < internalElements.length; i++) {
            String value = DocumentHelper.getSimpleElementText(internalElements[i]);
            String key = internalElements[i].getLocalName();

            if (key.equals("workflowVersion")) {
                List values = getValueList("http://apache.org/lenya/metadata/workflow/1.0", key);
                values.add(value);
            } else {
                List values = getValueList("http://apache.org/lenya/metadata/document/1.0", key);
                values.add(value);
            }
        }

        NamespaceHelper dcHelper = new NamespaceHelper(DublinCore.DC_NAMESPACE, "", xml);
        Element dcElement = helper.getFirstChild(metaElement, "dc");

        if (dcElement != null) {
            MetaDataRegistry registry = null;
            try {
                registry = (MetaDataRegistry) this.manager.lookup(MetaDataRegistry.ROLE);
                ElementSet dcElementSet = registry.getElementSet(DublinCore.DC_NAMESPACE);
                ElementSet dcTermSet = registry.getElementSet(DublinCore.DCTERMS_NAMESPACE);

                Element[] dcElements = dcHelper.getChildren(dcElement);
                for (int i = 0; i < dcElements.length; i++) {
                    String value = DocumentHelper.getSimpleElementText(dcElements[i]);

                    String key = dcElements[i].getLocalName();

                    if (dcElementSet.containsElement(key)) {
                        List values = getValueList(DublinCore.DC_NAMESPACE, key);
                        values.add(value);
                    } else if (dcTermSet.containsElement(key)) {
                        List values = getValueList(DublinCore.DCTERMS_NAMESPACE, key);
                        values.add(value);
                    } else {
                        throw new RepositoryException("The dublin core key [" + key
                                + "] is not supported.");
                    }
                }
            } catch (MetaDataException e) {
                throw e;
            } catch (Exception e) {
                throw new MetaDataException(e);
            } finally {
                if (registry != null) {
                    this.manager.release(registry);
                }
            }
        }

    }

    protected String[] getValues(String namespaceUri, String key, int revisionNumber)
            throws MetaDataException {
        List values = getValueList(namespaceUri, key);
        return (String[]) values.toArray(new String[values.size()]);
    }

    protected String[] getValues(String namespaceUri, String key) throws MetaDataException {
        List values = getValueList(namespaceUri, key);
        return (String[]) values.toArray(new String[values.size()]);
    }

    protected List getValueList(String namespaceUri, String key) throws MetaDataException {
        Map map = getMetaDataMap(namespaceUri);
        List values = (List) map.get(key);
        if (values == null) {
            synchronized (this) {
                values = new ArrayList();
                map.put(key, values);
            }
        }
        return values;
    }

    protected void addValue(String namespaceUri, String key, String value) throws MetaDataException {
        throw new IllegalStateException("Operation not supported");
    }

    protected void removeAllValues(String namespaceUri, String key) throws MetaDataException {
        throw new IllegalStateException("Operation not supported");
    }

    protected void setValue(String namespaceUri, String key, String value) throws MetaDataException {
        throw new IllegalStateException("Operation not supported");
    }

    public String[] getMetaDataNamespaceUris() throws MetaDataException {
        MetaDataRegistry registry = null;
        try {
            registry = (MetaDataRegistry) this.manager.lookup(MetaDataRegistry.ROLE);
            return registry.getNamespaceUris();
        } catch (ServiceException e) {
            throw new MetaDataException(e);
        } finally {
            if (registry != null) {
                this.manager.release(registry);
            }
        }
    }

    protected long getLastModified() throws RepositoryException {
        try {
            return SourceUtil.getLastModified(this.sourceUri, this.manager);
        } catch (Exception e) {
            throw new RepositoryException(e);
        }
    }

}
