/*
 * 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.tuscany;

import static java.util.Arrays.*;

import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

/**
 * Utility functions to help work efficiently with iterable lists, inspired from Lisp.
 */
public class IterableUtil {

    /**
     * Convert an array or a variable list of arguments to an iterable list.
     */
    public static <T> Iterable<T> list(final Object... a) {
        return new ArrayIterable<T>(a, 0);
    }

    /**
     * Convert an iterable list to a java.util.Collection.
     */
    @SuppressWarnings("unchecked")
    public static <T> Collection<T> collection(final Object l) {
        final Collection<T> c = new ArrayList<T>();
        for(final Object x : (Iterable<?>)l)
            c.add((T)x);
        return c;
    }

    /**
     * Construct a new list from an element and a list.
     */
    public static <T> Iterable<T> cons(final Object car, final Iterable<?> cdr) {
        return new PairIterable<T>(car, cdr);
    }

    /**
     * Return true if a list is nil (empty).
     */
    public static boolean isNull(final Object l) {
        if(l instanceof BasicIterable<?>)
            return ((BasicIterable<?>)l).isNull();
        if(l instanceof Collection<?>)
            return ((Collection<?>)l).isEmpty();
        return !((Iterable<?>)l).iterator().hasNext();
    }

    /**
     * Return the car (first element) of a list.
     */
    @SuppressWarnings("unchecked")
    public static <T> T car(final Object l) {
        if(l instanceof BasicIterable<?>)
            return ((BasicIterable<T>)l).car();
        if(l instanceof List<?>)
            return (T)((List<?>)l).get(0);
        return (T)((Iterable<?>)l).iterator().next();
    }

    /**
     * Return the cdr (rest after the first element) of a list.
     */
    @SuppressWarnings("unchecked")
    public static <T> Iterable<T> cdr(final Object l) {
        if(l instanceof BasicIterable<?>)
            return ((BasicIterable<T>)l).cdr();
        if(l instanceof List<?>)
            return new ListIterable<T>((List<?>)l, 1);
        if(l instanceof Collection<?>)
            return new ArrayIterable<T>(((Collection<?>)l).toArray(), 1);
        return new Iterable<T>() {
            public Iterator<T> iterator() {
                final Iterator<T> i = ((Iterable<T>)l).iterator();
                i.next();
                return i;
            }
        };
    }

    /**
     * Return the car of the cdr of a list.
     */
    @SuppressWarnings("unchecked")
    public static <T> T cadr(final Object l) {
        return (T)car(cdr(l));
    }

    /**
     * Return the cdr of the cdr of a list.
     */
    public static <T> Iterable<T> cddr(final Object l) {
        return cdr(cdr(l));
    }

    /**
     * Return the cdr of the cdr of the cdr of a list.
     */
    public static <T> Iterable<T> cdddr(final Object l) {
        return cdr(cdr(cdr(l)));
    }

    /**
     * Return the car of the cdr of the cdr of a list.
     */
    @SuppressWarnings("unchecked")
    public static <T> T caddr(final Object l) {
        return (T)car(cddr(l));
    }

    /**
     * Return the car of the cdr of the cdr of the cdr of a list.
     */
    @SuppressWarnings("unchecked")
    public static <T> T cadddr(final Object l) {
        return (T)car(cdddr(l));
    }

    /**
     * Appends a list and another list.
     */
    @SuppressWarnings("unchecked")
    public static <T> Iterable<T> append(final Object a, final Object b) {
        if (isNull(a))
            return (Iterable<T>)b;
        return cons(car(a), append(cdr(a), b));
    }

    /**
     * Return the first pair matching a key from a list of key value pairs.
     */
    public static <T> Iterable<T> assoc(final Object k, final Object l) {
        if(isNull(l))
            return list();
        if(k.equals(car(car(l))))
            return car(l);
        return assoc(k, cdr(l));
    }

    /**
     * Internal base implementation class for iterable and immutable lists.
     */
    static abstract class BasicIterable<T> extends AbstractList<T> {
        abstract T car();

        abstract Iterable<T> cdr();

        abstract Boolean isNull();

        @Override
        public int size() {
            return this.isNull()? 0 : 1 + ((List<T>)this.cdr()).size();
        }

        @Override
        public T get(final int index) {
            throw new UnsupportedOperationException();
        }
    }

    /**
     * Internal implementation of a list backed by an array.
     */
    static class ArrayIterable<T> extends BasicIterable<T> {
        final Object[] a;
        final int start;

        ArrayIterable(final Object[] a, final int start) {
            this.a = a;
            this.start = start;
        }

        @Override
        Boolean isNull() {
            return this.a.length - this.start == 0;
        }

        @SuppressWarnings("unchecked")
        @Override
        T car() {
            return (T)this.a[this.start];
        }

        @Override
        BasicIterable<T> cdr() {
            return new ArrayIterable<T>(this.a, this.start + 1);
        }

        @Override
        public Iterator<T> iterator() {
            return new Iterator<T>() {
                int i = ArrayIterable.this.start;

                public boolean hasNext() {
                    return this.i < ArrayIterable.this.a.length;
                }

                @SuppressWarnings("unchecked")
                public T next() {
                    return (T)ArrayIterable.this.a[this.i++];
                }

                public void remove() {
                    throw new UnsupportedOperationException();
                }
            };
        }
    }

    /**
     * Internal implementation of a list backed by a java.util.List.
     */
    static class ListIterable<T> extends BasicIterable<T> {
        final List<?> l;
        final int start;

        ListIterable(final List<?> l, final int start) {
            this.l = l;
            this.start = start;
        }

        @Override
        Boolean isNull() {
            return this.l.size() - this.start == 0;
        }

        @SuppressWarnings("unchecked")
        @Override
        T car() {
            return (T)this.l.get(this.start);
        }

        @Override
        BasicIterable<T> cdr() {
            return new ListIterable<T>(this.l, this.start + 1);
        }

        @Override
        public Iterator<T> iterator() {
            return new Iterator<T>() {
                int i = ListIterable.this.start;

                public boolean hasNext() {
                    return this.i < ListIterable.this.l.size();
                }

                @SuppressWarnings("unchecked")
                public T next() {
                    return (T)ListIterable.this.l.get(this.i++);
                }

                public void remove() {
                    throw new UnsupportedOperationException();
                }
            };
        }
    }

    /**
     * Internal implementation of a list backed by an element / iterable pair.
     */
    static class PairIterable<T> extends BasicIterable<T> {
        final Object car;
        final Iterable<?> cdr;

        PairIterable(final Object car, final Iterable<?> cdr) {
            this.car = car;
            this.cdr = cdr;
        }

        @Override
        Boolean isNull() {
            return false;
        }

        @SuppressWarnings("unchecked")
        @Override
        T car() {
            return (T)this.car;
        }

        @SuppressWarnings("unchecked")
        @Override
        Iterable<T> cdr() {
            return (Iterable<T>)this.cdr;
        }

        @Override
        public Iterator<T> iterator() {
            return new Iterator<T>() {
                boolean carIterator = true;
                Iterator<?> cdrIterator = PairIterable.this.cdr.iterator();

                public boolean hasNext() {
                    if(this.carIterator)
                        return true;
                    return this.cdrIterator.hasNext();
                }

                @SuppressWarnings("unchecked")
                public T next() {
                    if(this.carIterator) {
                        this.carIterator = false;
                        return (T)PairIterable.this.car;
                    }
                    return (T)this.cdrIterator.next();
                }

                public void remove() {
                    throw new UnsupportedOperationException();
                }
            };
        }
    }

    /**
     * Test the list functions.
     */
    static class Test {
        Boolean testList() {
            final Iterable<Object> l = list(2, 3, 4);
            assert car(l) == Integer.valueOf(2);
            assert cadr(l) == Integer.valueOf(3);
            assert caddr(l) == Integer.valueOf(4);

            final Iterable<Object> c = cons(0, cons(1, l));
            assert car(c) == Integer.valueOf(0);
            assert cadr(c) == Integer.valueOf(1);
            assert caddr(c) == Integer.valueOf(2);
            assert c.toString().equals("[0, 1, 2, 3, 4]");

            final Iterable<Object> cl = cons(0, cons(1, new ArrayList<Object>(asList(2, 3, 4))));
            assert car(cl) == Integer.valueOf(0);
            assert cadr(cl) == Integer.valueOf(1);
            assert caddr(cl) == Integer.valueOf(2);
            assert cl.toString().equals("[0, 1, 2, 3, 4]");

            final List<Object> jl = new ArrayList<Object>(collection(cl));
            assert jl.size() == 5;
            assert jl.get(0) == Integer.valueOf(0);
            assert jl.get(1) == Integer.valueOf(1);
            assert jl.get(2) == Integer.valueOf(2);

            final Iterable<Object> n = list();
            assert isNull(n);
            assert n.toString().equals("[]");

            final Iterable<Object> cn = cons(0, n);
            assert !isNull(cn);
            assert isNull(cdr(cn));
            assert cn.toString().equals("[0]");

            final Iterable<Object> al = new ArrayList<Object>(Arrays.asList(1, 2, 3));
            assert car(al) == Integer.valueOf(1);
            assert cadr(al) == Integer.valueOf(2);
            assert caddr(al) == Integer.valueOf(3);

            final Iterable<Object> a = list(0, 1, 2);
            final Iterable<Object> b = list(3, 4);
            final Iterable<Object> ab = append(a, b);
            assert ab.toString().equals("[0, 1, 2, 3, 4]");
            return true;
        }
    }

    public static void main(final String[] args) {
        System.out.println("Testing...");

        Test.class.getClassLoader().setDefaultAssertionStatus(true);
        new Test().testList();

        System.out.println("OK");
    }

}
