/*
 * Copyright 2013 Yuichiro Moriguchi
 *
 * Licensed 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 net.morilib.awk.nano.value;

import java.util.List;

import net.morilib.awk.nano.AwkCastException;
import net.morilib.awk.nano.io.AwkFiles;
import net.morilib.awk.nano.namespace.AwkNamespace;

/**
 * awkium関数オブジェクトのクラスです。
 * 
 * @author MORIGUCHI, Yuichiro 2013/03
 */
public abstract class AwkFunction extends AwkValue {

	/**
	 * 関数名です。
	 */
	protected String name;

	/**
	 * 関数が持つクロージャです。
	 */
	protected AwkNamespace env;

	/**
	 * 関数を生成します。
	 * 
	 * @param name 関数名
	 * @param env  含まれる環境
	 */
	protected AwkFunction(String name, AwkNamespace env) {
		this.name = name;
		this.env  = env;
	}

	/**
	 * 関数を適用します。
	 * 
	 * @param ns   名前空間
	 * @param o    ファイル管理
	 * @param args 引数
	 * @return 適用した結果の値
	 */
	public abstract AwkValue apply(AwkNamespace ns, AwkFiles o,
			List<AwkValue> args);

	/**
	 * 「コンストラクタ」を適用します。
	 * 
	 * @param ns   名前空間
	 * @param o    ファイル管理
	 * @param args 引数
	 * @return 新しいawkiumインスタンス
	 */
	public AwkValue init(AwkNamespace ns, AwkFiles o,
			List<AwkValue> args) {
		throw new AwkCastException("this is not a class");
	}

	/**
	 * 関数名を取得します。
	 * 
	 * @return 関数名
	 */
	public String getName() {
		return name;
	}

	/**
	 * 環境を取得します。
	 * 
	 * @return 環境
	 */
	public AwkNamespace getEnvironment() {
		return env;
	}

	public final boolean isFloat() {
		return false;
	}

	public final boolean isFunction() {
		return true;
	}

	public final boolean isInteger() {
		return false;
	}

	public final boolean isReal() {
		return false;
	}

	public boolean isFloatValue() {
		return false;
	}

	public boolean isIntegerValue() {
		return false;
	}

	public boolean isRealValue() {
		return false;
	}

	@Override
	public boolean isNegativeValue() {
		return false;
	}

	@Override
	public boolean isPositiveValue() {
		return false;
	}

	@Override
	public boolean isZeroValue() {
		return false;
	}

	public final boolean isRegex() {
		return false;
	}

	public final boolean isString() {
		return false;
	}

	public final boolean toBoolean(AwkNamespace ns) {
		return false;
	}

	/* (non-Javadoc)
	 * @see net.morilib.awk.value.AwkValue#toObject()
	 */
	public final Object toObject() {
		return this;
	}

	public String toString(AwkNamespace ns) {
		return "function " + getName();
	}

	public final int compareTo(AwkValue o, AwkNamespace ns) {
		if(o instanceof AwkUndefined) {
			return 1;
		} else if(o instanceof AwkFunction) {
			return 0;
		} else {
			return -1;
		}
	}

}
