/**
 * This file is part of Erjang - A JVM-based Erlang VM
 *
 * Copyright (c) 2009 by Trifork
 *
 * 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 erjang.m.erlang;

import erjang.BIF;
import erjang.EObject;
import erjang.ECons;
import erjang.ESeq;
import erjang.ERT;
import erjang.ESmall;
import erjang.ETuple;

import java.util.LinkedList;

/**
 * 
 */
public class ErlList {

	@BIF(name="--")
	public static ECons listDiff(EObject a1, EObject a2) {
		ESeq l1, l2;
		if ((l1 = a1.testSeq()) == null ||
			(l2 = a2.testSeq()) == null)
			throw ERT.badarg(a1,a2);

		if (l1.isNil()) return l1;

		// Step 1: Copy l1 to a temporary place.
		final EObject[] tmp = l1.toArray();

		// Step 2: Delete elements occurring l2 (but only once)
		int tmp_start = 0;
		for (ESeq cur = l2; !cur.isNil(); cur=cur.tail()) {
			EObject elm = cur.head();
			for (int i=tmp_start; i<tmp.length; i++) {
				if (tmp[i] != null && tmp[i].equalsExactly(elm)) {
					// Delete element
					tmp[i] = null;

					// Update tmp_start
					if (i==tmp_start) {
						do {
							tmp_start++;
						} while (tmp_start<tmp.length && tmp[tmp_start]==null);
						if (tmp_start == tmp.length) // No elements left.
							return ERT.NIL;
					}
					break; // Delete only one.
				}
			}
		}

		// Step 3: Convert back into list
		return ESeq.fromArraySkippingNulls(tmp, tmp_start, tmp.length);
	}
	
	@BIF
	public static EObject delete_element(EObject idx0, EObject tup0)
	{
		ESmall idx = idx0.testSmall();
		ETuple tup = tup0.testTuple();
		if (idx == null || tup == null || idx.value < 1 || idx.value > tup.arity())
			throw ERT.badarg(idx0, tup0);
		
		EObject[] vals = new EObject[tup.arity()-1];
		int target = 0;
		for (int i = 0; i < tup.arity(); i++) {
			if ((i+1) != idx.value) { 
				vals[target++] = tup.elm(i+1);
			}
		}
		
		return ETuple.make(vals);
	}
	
}

@@ -2355,10 +2355,529 @@
 );%0A%09%7D%0A%09%0A
+%09@BIF%0A%09public static EObject%0A%09insert_element(EObject idx0, EObject tup0, EObject term)%0A%09%7B%0A%09%09ESmall idx = idx0.testSmall();%0A%09%09ETuple tup = tup0.testTuple();%0A%09%09if (idx == null %7C%7C tup == null %7C%7C idx.value %3C 1 %7C%7C idx.value %3E tup.arity()+1)%0A%09%09%09throw ERT.badarg(idx0, tup0);%0A%09%09%0A%09%09EObject%5B%5D vals = new EObject%5Btup.arity()+1%5D;%0A%09%09int target = 0;%0A%09%09for (int i = 0; i %3C tup.arity(); i++) %7B%0A%09%09%09if ((i+1) == idx.value) %7B %0A%09%09%09%09vals%5Btarget++%5D = term;%0A%09%09%09%7D%0A%09%09%09%0A%09%09%09vals%5Btarget++%5D = tup.elm(i+1);%0A%09%09%7D%0A%09%09%0A%09%09return ETuple.make(vals);%0A%09%7D%0A%09%0A
 %7D%0A

Implement erlang:insert_element/3 BIF