/*
 * 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 freemarker.debug.impl;

import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import freemarker.cache.CacheStorage;
import freemarker.cache.SoftCacheStorage;
import freemarker.core.Configurable;
import freemarker.core.Environment;
import freemarker.debug.DebugModel;
import freemarker.debug.DebuggedEnvironment;
import freemarker.ext.util.IdentityHashMap;
import freemarker.template.Configuration;
import freemarker.template.SimpleCollection;
import freemarker.template.SimpleScalar;
import freemarker.template.Template;
import freemarker.template.TemplateCollectionModel;
import freemarker.template.TemplateHashModelEx;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.utility.UndeclaredThrowableException;

/**
 */
class RmiDebuggedEnvironmentImpl
extends
    RmiDebugModelImpl
implements
    DebuggedEnvironment {
    private static final long serialVersionUID = 1L;

    private static final CacheStorage storage = new SoftCacheStorage(new IdentityHashMap());
    private static final Object idLock = new Object();
    private static long nextId = 1;
    private static Set remotes = new HashSet();

    
    private boolean stopped = false;
    private final long id;
    
    private RmiDebuggedEnvironmentImpl(Environment env) throws RemoteException {
        super(new DebugEnvironmentModel(env), DebugModel.TYPE_ENVIRONMENT);
        synchronized (idLock) {
            id = nextId++;
        }
    }

    static synchronized Object getCachedWrapperFor(Object key)
    throws RemoteException {
        Object value = storage.get(key);
        if (value == null) {
            if (key instanceof TemplateModel) {
                int extraTypes;
                if (key instanceof DebugConfigurationModel) {
                    extraTypes = DebugModel.TYPE_CONFIGURATION;
                } else if (key instanceof DebugTemplateModel) {
                    extraTypes = DebugModel.TYPE_TEMPLATE;
                } else {
                    extraTypes = 0;
                }
                value = new RmiDebugModelImpl((TemplateModel) key, extraTypes);
            } else if (key instanceof Environment) {
                value = new RmiDebuggedEnvironmentImpl((Environment) key); 
            } else if (key instanceof Template) {
                value = new DebugTemplateModel((Template) key);
            } else if (key instanceof Configuration) {
                value = new DebugConfigurationModel((Configuration) key);
            }
        }
        if (value != null) {
            storage.put(key, value);
        }
        if (value instanceof Remote) {
            remotes.add(value);
        }
        return value;
    }

    // TODO See in SuppressFBWarnings
    @SuppressFBWarnings(value="NN_NAKED_NOTIFY", justification="Will have to be re-desigend; postponed.")
    public void resume() {
        synchronized (this) {
            notify();
        }
    }

    public void stop() {
        stopped = true;
        resume();
    }

    public long getId() {
        return id;
    }
    
    boolean isStopped() {
        return stopped;
    }
    
    private abstract static class DebugMapModel implements TemplateHashModelEx {
        public int size() {
            return keySet().size();
        }

        public TemplateCollectionModel keys() {
            return new SimpleCollection(keySet());
        }

        public TemplateCollectionModel values() throws TemplateModelException {
            Collection keys = keySet();
            List list = new ArrayList(keys.size());
            
            for (Iterator it = keys.iterator(); it.hasNext(); ) {
                list.add(get((String) it.next()));
            }
            return new SimpleCollection(list);
        }

        public boolean isEmpty() {
            return size() == 0;
        }
        
        abstract Collection keySet();

        static List composeList(Collection c1, Collection c2) {
            List list = new ArrayList(c1);
            list.addAll(c2);
            Collections.sort(list);
            return list;
        }
    }
    
    private static class DebugConfigurableModel extends DebugMapModel {
        static final List KEYS = Arrays.asList(new String[]
        {
            Configurable.ARITHMETIC_ENGINE_KEY,
            Configurable.BOOLEAN_FORMAT_KEY,
            Configurable.CLASSIC_COMPATIBLE_KEY,
            Configurable.LOCALE_KEY,
            Configurable.NUMBER_FORMAT_KEY,
            Configurable.OBJECT_WRAPPER_KEY,
            Configurable.TEMPLATE_EXCEPTION_HANDLER_KEY
        });

        final Configurable configurable;
        
        DebugConfigurableModel(Configurable configurable) {
            this.configurable = configurable;
        }
        
        @Override
        Collection keySet() {
            return KEYS;
        }
        
        public TemplateModel get(String key) throws TemplateModelException {
            String s = configurable.getSetting(key);
            return s == null ? null : new SimpleScalar(s);
        }

    }
    
    private static class DebugConfigurationModel extends DebugConfigurableModel {
        private static final List KEYS = composeList(DebugConfigurableModel.KEYS, Collections.singleton("sharedVariables"));

        private TemplateModel sharedVariables = new DebugMapModel()
        {
            @Override
            Collection keySet() {
                return ((Configuration) configurable).getSharedVariableNames();
            }
        
            public TemplateModel get(String key) {
                return ((Configuration) configurable).getSharedVariable(key);
            }
        };
        
        DebugConfigurationModel(Configuration config) {
            super(config);
        }
        
        @Override
        Collection keySet() {
            return KEYS;
        }

        @Override
        public TemplateModel get(String key) throws TemplateModelException {
            if ("sharedVariables".equals(key)) {
                return sharedVariables; 
            } else {
                return super.get(key);
            }
        }
    }
    
    private static class DebugTemplateModel extends DebugConfigurableModel {
        private static final List KEYS = composeList(DebugConfigurableModel.KEYS, 
            Arrays.asList(new String[] {
                "configuration", 
                "name",
                }));
    
        private final SimpleScalar name;

        DebugTemplateModel(Template template) {
            super(template);
            this.name = new SimpleScalar(template.getName());
        }

        @Override
        Collection keySet() {
            return KEYS;
        }

        @Override
        public TemplateModel get(String key) throws TemplateModelException {
            if ("configuration".equals(key)) {
                try {
                    return (TemplateModel) getCachedWrapperFor(((Template) configurable).getConfiguration());
                } catch (RemoteException e) {
                    throw new TemplateModelException(e);
                }
            }
            if ("name".equals(key)) {
                return name;
            }
            return super.get(key);
        }
    }

    private static class DebugEnvironmentModel extends DebugConfigurableModel {
        private static final List KEYS = composeList(DebugConfigurableModel.KEYS, 
            Arrays.asList(new String[] {
                "currentNamespace",
                "dataModel",
                "globalNamespace",
                "knownVariables",
                "mainNamespace",
                "template",
                 }));
    
        private TemplateModel knownVariables = new DebugMapModel()
        {
            @Override
            Collection keySet() {
                try {
                    return ((Environment) configurable).getKnownVariableNames();
                } catch (TemplateModelException e) {
                    throw new UndeclaredThrowableException(e);
                }
            }
        
            public TemplateModel get(String key) throws TemplateModelException {
                return ((Environment) configurable).getVariable(key);
            }
        };
         
        DebugEnvironmentModel(Environment env) {
            super(env);
        }

        @Override
        Collection keySet() {
            return KEYS;
        }

        @Override
        public TemplateModel get(String key) throws TemplateModelException {
            if ("currentNamespace".equals(key)) {
                return ((Environment) configurable).getCurrentNamespace();
            }
            if ("dataModel".equals(key)) {
                return ((Environment) configurable).getDataModel();
            }
            if ("globalNamespace".equals(key)) {
                return ((Environment) configurable).getGlobalNamespace();
            }
            if ("knownVariables".equals(key)) {
                return knownVariables;
            }
            if ("mainNamespace".equals(key)) {
                return ((Environment) configurable).getMainNamespace();
            }
            if ("template".equals(key)) {
                try {
                    return (TemplateModel) getCachedWrapperFor(((Environment) configurable).getTemplate());
                } catch (RemoteException e) {
                    throw new TemplateModelException(e);
                }
            }
            return super.get(key);
        }
    }

    public static void cleanup() {
        for (Iterator i = remotes.iterator(); i.hasNext(); ) {
            Object remoteObject = i.next();
            try {
                UnicastRemoteObject.unexportObject((Remote) remoteObject, true);
            } catch (Exception e) {
            }
        }
    }
}
