/*
 * 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.cocoon.el.impl.objectmodel;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Map;

import org.apache.cocoon.el.objectmodel.ObjectModel;
import org.apache.cocoon.el.objectmodel.ObjectModelProvider;
import org.apache.commons.collections.ArrayStack;
import org.apache.commons.collections.KeyValue;
import org.apache.commons.collections.MultiMap;
import org.apache.commons.collections.iterators.ReverseListIterator;
import org.apache.commons.collections.keyvalue.DefaultKeyValue;
import org.apache.commons.collections.map.AbstractMapDecorator;
import org.apache.commons.collections.map.MultiValueMap;
import org.apache.commons.jxpath.DynamicPropertyHandler;
import org.apache.commons.jxpath.JXPathBeanInfo;
import org.apache.commons.jxpath.JXPathIntrospector;

/**
 * Prototype implementation of {@link ObjectModel} interface. It <b>must</b> be initialized manually for now.
 *
 */
public class ObjectModelImpl extends AbstractMapDecorator implements ObjectModel {
    //FIXME: It seems that there is no easy way to reuse MuliValueMap

    private static final String SEGMENT_SEPARATOR = "/";

    private ArrayStack localContexts;
    private Map singleValueMap;
    private MultiMap multiValueMap;
    private MultiMap multiValueMapForLocated;
    private Map initialEntries;

    //FIXME: This is a temporary solution
    private boolean modified;


    public ObjectModelImpl() {
        singleValueMap = new HashMap();
        //FIXME: Not sure if this makes sense
        //super.map = UnmodifiableMap.decorate(singleValueMap);
        super.map = singleValueMap;
        localContexts = new ArrayStack();
        multiValueMap = MultiValueMap.decorate(new HashMap(), StackReversedIteration.class);
        multiValueMapForLocated = MultiValueMap.decorate(new HashMap(), StackReversedIteration.class);
    }

    public static class StackReversedIteration extends ArrayStack {

        public Iterator iterator() {
            return new ReverseListIterator(this);
        }

        public ListIterator listIterator() {
            throw new UnsupportedOperationException();
        }
    }

    public Object get(Object key) {
        //FIXME: This should be done more elegantly
        if ("this".equals(key)) {
            return this;
        }

        return super.get(key);
    }

    public MultiMap getAll() {
        return UnmodifiableMultiMap.decorate(multiValueMap);
    }

    public Object put(Object key, Object value) {
        modified = true;
        if (!localContexts.empty()) {
            ((ArrayStack) localContexts.peek()).push(new DefaultKeyValue(key, value));
        }

        singleValueMap.put(key, value);
        multiValueMap.put(key, value);

        return value;
    }

    public void putAll(Map mapToCopy) {
        modified = true;
        if (!localContexts.empty()) {
            ArrayStack entries = (ArrayStack)localContexts.peek();
            for (Iterator keysIterator = mapToCopy.keySet().iterator(); keysIterator.hasNext();) {
                Object key = keysIterator.next();
                entries.push(new DefaultKeyValue(key, mapToCopy.get(key)));
            }
        }

        singleValueMap.putAll(mapToCopy);
        multiValueMap.putAll(mapToCopy);
    }

    /**
     * Locates map at given path
     * @param path where Map can be found
     * @param createIfNeeded indicates if map(s) should be created if no corresponding found
     * @return located Map or null if <code>createIfNeeded</code> is false and Map cannot be found
     */
    private Map locateMapAt(String path, boolean createIfNeeded) {
        if (path.lastIndexOf(SEGMENT_SEPARATOR) == -1) {
            return this;
        }

        Map map = this;
        int segmentBegin = 0;
        int segmentEnd = path.indexOf(SEGMENT_SEPARATOR);
        while (segmentEnd != -1) {
            String key = path.substring(segmentBegin, segmentEnd);
            if (map.containsKey(key)) {
                Object obj = map.get(key);
                if (!(obj instanceof Map)) {
                    throw new ClassCastException("Object at path " + path.substring(0, segmentEnd) + "is not a Map");
                }

                map = (Map)obj;
            } else {
                if (!createIfNeeded) {
                    return null;
                }

                Map newMap = new HashMap();
                map.put(key, newMap);
                map = newMap;
            }
            segmentBegin = segmentEnd + 1;
            segmentEnd = path.indexOf(SEGMENT_SEPARATOR, segmentBegin);
        }

        return map;
    }

    public void putAt(String path, Object value) {
        if (path == null) {
            throw new NullPointerException("Path cannot be null.");
        }
        if (path.length() == 0) {
            throw new IllegalArgumentException("Path cannot be empty");
        }

        Map map = locateMapAt(path, true);
        String key = path.substring(path.lastIndexOf(SEGMENT_SEPARATOR) + 1, path.length());
        if (!localContexts.empty()) {
            ((ArrayStack) localContexts.peek()).push(new PathValue(path, value));
        }
        map.put(key, value);
    }

    private void removeAt(String path, Object value) {
        if (path == null) {
            throw new NullPointerException("Path cannot be null.");
        }
        if (path.length() == 0) {
            throw new IllegalArgumentException("Path cannot be empty");
        }

        Map map = locateMapAt(path, false);
        String key = path.substring(path.lastIndexOf(SEGMENT_SEPARATOR) + 1, path.length());
        if (map == null) {
            return;
        }

        multiValueMapForLocated.remove(key, value);
        if (multiValueMap.containsKey(key)) {
            map.put(key, ((StackReversedIteration) multiValueMap.get(key)).peek());
        } else {
            map.remove(key);
        }
    }

    public void cleanupLocalContext() {
        if (localContexts.empty()) {
            throw new IllegalStateException("Local contexts stack is empty");
        }

        ArrayStack removeEntries = (ArrayStack)localContexts.pop();
        while (!removeEntries.isEmpty()) {
            if (removeEntries.peek() instanceof PathValue) {
                PathValue entry = (PathValue)removeEntries.pop();
                removeAt(entry.getPath(), entry.getValue());
            } else {
                KeyValue entry = (KeyValue)removeEntries.pop();
                Object key = entry.getKey();
                Object value = entry.getValue();

                multiValueMap.remove(key, value);
                if (multiValueMap.containsKey(key)) {
                    singleValueMap.put(key, ((StackReversedIteration) multiValueMap.get(key)).peek());
                } else {
                    singleValueMap.remove(key);
                }
            }
        }
    }

    public void markLocalContext() {
        localContexts.push(new ArrayStack());
    }

    public Map getInitialEntries() {
        return initialEntries;
    }

    public void setInitialEntries(Map initialEntries) {
        if (this.initialEntries != null) {
            throw new IllegalStateException("Object Model has initial entries set already.");
        }

        this.initialEntries = initialEntries;
        for (Iterator keysIterator = initialEntries.keySet().iterator(); keysIterator.hasNext(); ) {
            Object key = keysIterator.next();
            put(key, ((ObjectModelProvider)initialEntries.get(key)).getObject());
        }

        this.modified = false;
    }

    public void fillContext() {
        // Hack: I use jxpath to populate the context object's properties
        // in the jexl context
        Object contextObject = get(CONTEXTBEAN);
        if (contextObject == null) {
            //nothing to do
            return;
        }

        // FIXME Exception Handling
        final JXPathBeanInfo bi =
            JXPathIntrospector.getBeanInfo(contextObject.getClass());
        if (bi.isDynamic()) {
            Class cl = bi.getDynamicPropertyHandlerClass();
            try {
                DynamicPropertyHandler h =
                    (DynamicPropertyHandler) cl.newInstance();
                String[] result = h.getPropertyNames(contextObject);
                int len = result.length;
                for (int i = 0; i < len; i++) {
                    try {
                        put(result[i], h.getProperty(contextObject, result[i]));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            PropertyDescriptor[] props =  bi.getPropertyDescriptors();
            int len = props.length;
            for (int i = 0; i < len; i++) {
                try {
                    Method read = props[i].getReadMethod();
                    if (read != null) {
                        put(props[i].getName(),
                            read.invoke(contextObject, null));
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private final class PathValue {
        private String path;
        private Object value;

        public PathValue(String path, Object value) {
            this.path = path;
            this.value = value;
        }

        public String getPath() {
            return this.path;
        }

        public Object getValue() {
            return this.value;
        }

    }

    /* (non-Javadoc)
     * @see ObjectModel#setParent(ObjectModel)
     */
    public void setParent(ObjectModel parentObjectModel) {
        if (this.modified) {
            throw new IllegalStateException("Setting parent may occur only if Object Model is empty.");
        }

        singleValueMap.putAll(parentObjectModel);
        multiValueMap.putAll(parentObjectModel.getAll());
    }
}
