/*
 * 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 aQute.shell.runtime;

import java.io.*;
import java.lang.reflect.*;
import java.util.*;

import org.osgi.service.command.*;

public class CommandSessionImpl implements CommandSession, Converter {
	String						COLUMN			= "%-20s %s\n";
	InputStream in;
	PrintStream out;
	PrintStream err;
	CommandShellImpl service;
	Map<Object, Object> variables = new HashMap<Object, Object>();

	CommandSessionImpl(CommandShellImpl service, InputStream in,
			PrintStream out, PrintStream err) {
		this.service = service;
		this.in = in;
		this.out = out;
		this.err = err;
	}

	public void close() {
	}

	public Object execute(CharSequence commandline) throws Exception {
		assert service != null;
		assert service.threadIO != null;
		
		Closure impl = new Closure(this, null, commandline);
		Object result = impl.execute(this, null);
		return result;
	}

	public InputStream getKeybord() {
		return in;
	}

	public Object get(String name) {
		if (variables != null && variables.containsKey(name))
			return variables.get(name);

		return service.get(name);
	}

	public void put(String name, Object value) {
		variables.put(name, value);
	}

	public PrintStream getConsole() {
		return out;
	}
	
	
	@SuppressWarnings("unchecked")
	public
	CharSequence format(Object target, int level, Converter escape ) throws Exception {
		if (target == null)
			return "null";

		if (target instanceof CharSequence )
			return (CharSequence) target;
		
		for (Converter c : service.converters) {
			CharSequence s = c.format(target, level, this);
			if (s != null)
				return s;
		}

		if (target.getClass().isArray()) {
			if ( target.getClass().getComponentType().isPrimitive()) {
				if ( target.getClass().getComponentType() == boolean.class ) 
					return Arrays.toString((boolean[]) target);
				else if ( target.getClass().getComponentType() == byte.class ) 
					return Arrays.toString((byte[]) target);
				else if ( target.getClass().getComponentType() == short.class ) 
					return Arrays.toString((short[]) target);
				else if ( target.getClass().getComponentType() == int.class ) 
					return Arrays.toString((int[]) target);
				else if ( target.getClass().getComponentType() == long.class ) 
					return Arrays.toString((long[]) target);
				else if ( target.getClass().getComponentType() == float.class ) 
					return Arrays.toString((float[]) target);
				else if ( target.getClass().getComponentType() == double.class ) 
					return Arrays.toString((double[]) target);
				else if ( target.getClass().getComponentType() == char.class ) 
					return Arrays.toString((char[]) target);
			}
			target = Arrays.asList((Object[]) target);
		}
		if (target instanceof Collection) {
			if (level == Converter.INSPECT) {
				StringBuilder sb = new StringBuilder();
				Collection<?> c = (Collection<?>) target;
				for (Object o : c) {
					sb.append(format(o, level + 1, this));
					sb.append("\n");
				}
				return sb;
			} else if (level == Converter.LINE) {
				StringBuilder sb = new StringBuilder();
				String del = "[";
				Collection<?> c = (Collection<?>) target;
				for (Object o : c) {
					sb.append(del);
					sb.append(format(o, level + 1, this));
					del = ", ";
				}
				sb.append("]");
				return sb;
			}
		}
		if ( target instanceof Dictionary ) {
			Map<Object,Object> result = new HashMap<Object,Object>();
			for ( Enumeration e = ((Dictionary)target).keys(); e.hasMoreElements(); ) {
				Object key = e.nextElement();
				result.put(key, ((Dictionary)target).get(key));
			}
			target = result;
		}
		if (target instanceof Map) {
			if (level == Converter.INSPECT) {
				StringBuilder sb = new StringBuilder();
				Map<?,?> c = (Map<?,?>) target;
				for (Map.Entry<?,?> entry : c.entrySet()) {
					CharSequence key = format(entry.getKey(), level + 1, this);
					sb.append(key);
					for ( int i=key.length(); i<20; i++ )
						sb.append(' ');
					sb.append(format(entry.getValue(), level + 1, this));
					sb.append("\n");
				}
				return sb;
			} else if (level == Converter.LINE) {
				StringBuilder sb = new StringBuilder();
				String del = "[";
				Map<?,?> c = (Map<?,?>) target;
				for (Map.Entry<?,?> entry : c.entrySet()) {
					sb.append(del);
					sb.append(format(entry, level + 1,this));
					del = ", ";
				}
				sb.append("]");
				return sb;
			}
		}
		if (level == Converter.INSPECT)
			return inspect(target);
		else
			return target.toString();
	}

	CharSequence inspect(Object b) {
		boolean found = false;
		Formatter f = new Formatter();
		Method methods[] = b.getClass().getMethods();
		for (Method m : methods) {
			try {
				String name = m.getName();
				if (m.getName().startsWith("get")
						&& !m.getName().equals("getClass")
						&& m.getParameterTypes().length == 0
						&& Modifier.isPublic(m.getModifiers())) {
					found = true;
					name = name.substring(3);
					m.setAccessible(true);
					Object value = m.invoke(b, (Object[]) null);
					f.format(COLUMN, name, format(value, Converter.LINE, this));
				}
			} catch (IllegalAccessException e) {
				// Ignore
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (found)
			return (StringBuilder) f.out();
		else
			return b.toString();
	}


	public Object convert(Class<?> desiredType, Object in)  {
		return service.convert(desiredType, in);
	}

	public CharSequence format(Object result, int inspect) {
	    try {
		return format(result,inspect,this);
	    } catch(Exception e ) {
	        return "<can not format " + result + ":" + e;
	    }
	}

}
