/*
 * 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.
 */
/*
 * $Id$
 */

package org.apache.xalan.xsltc.compiler.util;

import java.util.Vector;

/**
 * @author Jacek Ambroziak
 * @author Santiago Pericas-Geertsen
 */
public final class MethodType extends Type {
    private final Type _resultType;	
    private final Vector _argsType;
	
    public MethodType(Type resultType) {
	_argsType = null;
	_resultType = resultType;
    }

    public MethodType(Type resultType, Type arg1) {
	if (arg1 != Type.Void) {
	    _argsType = new Vector();
	    _argsType.addElement(arg1);
	}
	else {
	    _argsType = null;
	}
	_resultType = resultType;
    }

    public MethodType(Type resultType, Type arg1, Type arg2) {
	_argsType = new Vector(2);
	_argsType.addElement(arg1);
	_argsType.addElement(arg2);
	_resultType = resultType;
    }

    public MethodType(Type resultType, Type arg1, Type arg2, Type arg3) {
	_argsType = new Vector(3);
	_argsType.addElement(arg1);
	_argsType.addElement(arg2);
	_argsType.addElement(arg3);
	_resultType = resultType;
    }

    public MethodType(Type resultType, Vector argsType) {
	_resultType = resultType;
	_argsType = argsType.size() > 0 ? argsType : null;
    }

    public String toString() {
	StringBuffer result = new StringBuffer("method{");
	if (_argsType != null) {
	    final int count = _argsType.size();
	    for (int i=0; i<count; i++) {
		result.append(_argsType.elementAt(i));
		if (i != (count-1)) result.append(',');
	    }
	}
	else {
	    result.append("void");
	}
	result.append('}');
	return result.toString();
    }

    public String toSignature() {
	return toSignature("");
    }

    /**
     * Returns the signature of this method that results by adding
     * <code>lastArgSig</code> to the end of the argument list.
     */
    public String toSignature(String lastArgSig) {
	final StringBuffer buffer = new StringBuffer();
	buffer.append('(');
	if (_argsType != null) {
	    final int n = _argsType.size();
	    for (int i = 0; i < n; i++) {
		buffer.append(((Type)_argsType.elementAt(i)).toSignature());
	    }
	}
	return buffer
	    .append(lastArgSig)
	    .append(')')
	    .append(_resultType.toSignature())
	    .toString();
    }

    public org.apache.bcel.generic.Type toJCType() {
	return null;	// should never be called
    }

    public boolean identicalTo(Type other) {
	boolean result = false;
	if (other instanceof MethodType) {
	    final MethodType temp = (MethodType) other;
	    if (_resultType.identicalTo(temp._resultType)) {
		final int len = argsCount();
		result = len == temp.argsCount();
		for (int i = 0; i < len && result; i++) {
		    final Type arg1 = (Type)_argsType.elementAt(i);
		    final Type arg2 = (Type)temp._argsType.elementAt(i);
		    result = arg1.identicalTo(arg2);
		}
	    }
	}
	return result;	
    }
	
    public int distanceTo(Type other) {
	int result = Integer.MAX_VALUE;
	if (other instanceof MethodType) {
	    final MethodType mtype = (MethodType) other;
	    if (_argsType != null) {
		final int len = _argsType.size();
		if (len == mtype._argsType.size()) {
		    result = 0;
		    for (int i = 0; i < len; i++) {
			Type arg1 = (Type) _argsType.elementAt(i);
			Type arg2 = (Type) mtype._argsType.elementAt(i);
			final int temp = arg1.distanceTo(arg2);
			if (temp == Integer.MAX_VALUE) {
			    result = temp;  // return MAX_VALUE
			    break;
			}
			else {
			    result += arg1.distanceTo(arg2);
			}
		    }
		}
	    }
	    else if (mtype._argsType == null) {
		result = 0;   // both methods have no args
	    }
	}
	return result;
    }
		
    public Type resultType() {
	return _resultType;
    }
		
    public Vector argsType() {
	return _argsType;
    }

    public int argsCount() {
	return _argsType == null ? 0 : _argsType.size();
    }
}
