/*
 * 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.felix.gogo.runtime;

import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArraySet;

import org.apache.felix.service.command.*;
import org.apache.felix.service.threadio.ThreadIO;

public class CommandProcessorImpl implements CommandProcessor
{
    protected final Set<Converter> converters = new CopyOnWriteArraySet<>();
    protected final Set<CommandSessionListener> listeners = new CopyOnWriteArraySet<>();
    protected final ConcurrentMap<String, Map<Object, Integer>> commands = new ConcurrentHashMap<>();
    protected final Map<String, Object> constants = new ConcurrentHashMap<>();
    protected final ThreadIO threadIO;
    protected final WeakHashMap<CommandSession, Object> sessions = new WeakHashMap<>();
    protected boolean stopped;

    public CommandProcessorImpl()
    {
        this(null);
    }

    public CommandProcessorImpl(ThreadIO tio)
    {
        threadIO = tio;
    }

    @Override
    public CommandSessionImpl createSession(CommandSession parent) {
        synchronized (sessions) {
            if (stopped)
            {
                throw new IllegalStateException("CommandProcessor has been stopped");
            }
            if (!sessions.containsKey(parent) || !(parent instanceof CommandSessionImpl)) {
                throw new IllegalArgumentException();
            }
            CommandSessionImpl session = new CommandSessionImpl(this, (CommandSessionImpl) parent);
            sessions.put(session, null);
            return session;
        }
    }

    public CommandSessionImpl createSession(InputStream in, OutputStream out, OutputStream err)
    {
        synchronized (sessions)
        {
            if (stopped)
            {
                throw new IllegalStateException("CommandProcessor has been stopped");
            }
            CommandSessionImpl session = new CommandSessionImpl(this, in, out, err);
            sessions.put(session, null);
            return session;
        }
    }

    void closeSession(CommandSessionImpl session)
    {
        synchronized (sessions)
        {
            sessions.remove(session);
        }
    }

    public void stop()
    {
        synchronized (sessions)
        {
            stopped = true;
            // Create a copy, as calling session.close() will remove the session from the map
            CommandSession[] toClose = this.sessions.keySet().toArray(new CommandSession[this.sessions.size()]);
            for (CommandSession session : toClose)
            {
                session.close();
            }
            // Just in case...
			sessions.clear();
        }
    }

    public void addConverter(Converter c)
    {
        converters.add(c);
    }

    public void removeConverter(Converter c)
    {
        converters.remove(c);
    }

    public void addListener(CommandSessionListener l)
    {
        listeners.add(l);
    }

    public void removeListener(CommandSessionListener l)
    {
        listeners.remove(l);
    }

    public Set<String> getCommands()
    {
        return Collections.unmodifiableSet(commands.keySet());
    }

    protected Function getCommand(String name, final Object path)
    {
        int colon = name.indexOf(':');

        if (colon < 0)
        {
            return null;
        }

        name = name.toLowerCase();
        String cfunction = name.substring(colon);
        boolean anyScope = (colon == 1 && name.charAt(0) == '*');

        Map<Object, Integer> cmdMap = commands.get(name);

        if (null == cmdMap && anyScope)
        {
            String scopePath = (null == path ? "*" : path.toString());

            for (String scope : scopePath.split(":"))
            {
                if (scope.equals("*"))
                {
                    for (Entry<String, Map<Object, Integer>> entry : commands.entrySet())
                    {
                        if (entry.getKey().endsWith(cfunction))
                        {
                            cmdMap = entry.getValue();
                            break;
                        }
                    }
                }
                else
                {
                    cmdMap = commands.get(scope + cfunction);
                    if (cmdMap != null)
                    {
                        break;
                    }
                }
            }
        }

        Object cmd = null;
        if (cmdMap != null && !cmdMap.isEmpty())
        {
            for (Entry<Object, Integer> e : cmdMap.entrySet())
            {
                if (cmd == null || e.getValue() > cmdMap.get(cmd))
                {
                    cmd = e.getKey();
                }
            }
        }
        if ((null == cmd) || (cmd instanceof Function))
        {
            return (Function) cmd;
        }

        return new CommandProxy(cmd, cfunction.substring(1));
    }

    @Descriptor("add commands")
    public void addCommand(@Descriptor("scope") String scope, @Descriptor("target") Object target)
    {
        Class<?> tc = (target instanceof Class<?>) ? (Class<?>) target : target.getClass();
        addCommand(scope, target, tc);
    }

    @Descriptor("add commands")
    public void addCommand(@Descriptor("scope") String scope, @Descriptor("target") Object target, @Descriptor("functions") Class<?> functions)
    {
        addCommand(scope, target, functions, 0);
    }

    public void addCommand(String scope, Object target, Class<?> functions, int ranking)
    {
        if (target == null)
        {
            return;
        }

        String[] names = getFunctions(functions);
        for (String function : names)
        {
            addCommand(scope, target, function, ranking);
        }
    }

    public Object addConstant(String name, Object target)
    {
        return constants.put(name, target);
    }

    public Object removeConstant(String name)
    {
        return constants.remove(name);
    }

    public void addCommand(String scope, Object target, String function)
    {
        addCommand(scope, target, function, 0);
    }

    public void addCommand(String scope, Object target, String function, int ranking)
    {
        String key = (scope + ":" + function).toLowerCase();
        Map<Object, Integer> cmdMap = commands.get(key);
        if (cmdMap == null)
        {
            commands.putIfAbsent(key, new LinkedHashMap<Object, Integer>());
            cmdMap = commands.get(key);
        }
        cmdMap.put(target, ranking);
    }

    public void removeCommand(String scope, String function)
    {
        // TODO: WARNING: this method does remove all mapping for scope:function
        String key = (scope + ":" + function).toLowerCase();
        commands.remove(key);
    }

    public void removeCommand(String scope, String function, Object target)
    {
        // TODO: WARNING: this method does remove all mapping for scope:function
        String key = (scope + ":" + function).toLowerCase();
        Map<Object, Integer> cmdMap = commands.get(key);
        if (cmdMap != null)
        {
            cmdMap.remove(target);
        }
    }

    public void removeCommand(Object target)
    {
        for (Map<Object, Integer> cmdMap : commands.values())
        {
            cmdMap.remove(target);
        }
    }

    private String[] getFunctions(Class<?> target)
    {
        String[] functions;
        Set<String> list = new TreeSet<>();
        Method methods[] = target.getMethods();
        for (Method m : methods)
        {
            if (m.getDeclaringClass().equals(Object.class))
            {
                continue;
            }
            list.add(m.getName());
            if (m.getName().startsWith("get"))
            {
                String s = m.getName().substring(3);
                if (s.length() > 0)
                {
                    list.add(s.substring(0, 1).toLowerCase() + s.substring(1));
                }
            }
        }

        functions = list.toArray(new String[list.size()]);
        return functions;
    }

    public Object convert(CommandSession session, Class<?> desiredType, Object in)
    {
        int[] cost = new int[1];
        Object ret = Reflective.coerce(session, desiredType, in, cost);
        if (ret == Reflective.NO_MATCH)
        {
            throw new IllegalArgumentException(String.format(
                    "Cannot convert %s(%s) to %s", in, in != null ? in.getClass() : "null", desiredType));
        }
        return ret;
    }

    Object doConvert(Class<?> desiredType, Object in)
    {
        for (Converter c : converters)
        {
            try
            {
                Object converted = c.convert(desiredType, in);
                if (converted != null)
                {
                    return converted;
                }
            }
            catch (Exception e)
            {
                // Ignore
                e.getCause();
            }
        }

        return null;
    }

    // eval is needed to force expansions to be treated as commands (FELIX-1473)
    public Object eval(CommandSession session, Object[] argv) throws Exception
    {
        StringBuilder buf = new StringBuilder();

        for (Object arg : argv)
        {
            if (buf.length() > 0)
                buf.append(' ');
            buf.append(arg);
        }

        return session.execute(buf);
    }

    void beforeExecute(CommandSession session, CharSequence commandline)
    {
        for (CommandSessionListener l : listeners)
        {
            try
            {
                l.beforeExecute(session, commandline);
            }
            catch (Throwable t)
            {
                // Ignore
            }
        }
    }

    void afterExecute(CommandSession session, CharSequence commandline, Exception exception)
    {
        for (CommandSessionListener l : listeners)
        {
            try
            {
                l.afterExecute(session, commandline, exception);
            }
            catch (Throwable t)
            {
                // Ignore
            }
        }
    }

    void afterExecute(CommandSession session, CharSequence commandline, Object result)
    {
        for (CommandSessionListener l : listeners)
        {
            try
            {
                l.afterExecute(session, commandline, result);
            }
            catch (Throwable t)
            {
                // Ignore
            }
        }
    }

    public Object expr(CommandSessionImpl session, CharSequence expr)
    {
        return new Expression(expr.toString()).eval(session.variables);
    }
}
