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

import java.util.*;
import java.io.*;
import org.apache.hadoop.io.*;
import org.apache.hadoop.fs.*;


/**
 *   A sequence of MRData.
 *   There are 3 kinds of Bag implementations, which are converted at run-time, when necessary:
 *   1) vector-based (materialized): used for small bags (when size is less than Config.max_materialized_bag);
 *   2) stream-based: can be traversed only once; implemented as Java iterators;
 *   3) spilled to a local file: can be accessed multiple times
 */
public class Bag extends MRData implements Iterable<MRData> {
    private final static long serialVersionUID = 64629834894869L;
    enum Modes { STREAMED, MATERIALIZED, SPILLED };
    private transient Modes mode;
    private transient ArrayList<MRData> content;      // content of a materialized bag
    private transient BagIterator iterator;           // iterator for a streamed bag
    private transient boolean consumed;               // true, if the stream has already been used
    private transient String path;                    // local path that contains the spilled bag
    private transient SequenceFile.Writer writer;     // the file writer for spiled bags

    /**
     * create an empty bag as an ArrayList
     */
    public Bag () {
        mode = Modes.MATERIALIZED;
        content = new ArrayList<MRData>();
    }

    /**
     * create an empty bag as an ArrayList with a given capacity
     * @param size initial capacity
     */
    public Bag ( final int size ) {
        mode = Modes.MATERIALIZED;
        content = new ArrayList<MRData>(size);
    }

    /**
     * in-memory Bag construction (an ArrayList) initialized with data
     * @param as a vector of MRData to insert in the Bag
     */
    public Bag ( final MRData ...as ) {
        mode = Modes.MATERIALIZED;
        content = new ArrayList<MRData>(as.length);
        for ( MRData a: as )
            content.add(a);
    }

    /**
     * in-memory Bag construction (an ArrayList) initialized with data
     * @param as a vector of MRData to insert in the Bag
     */
    public Bag ( final List<MRData> as ) {
        mode = Modes.MATERIALIZED;
        content = new ArrayList<MRData>(as.size());
        for ( MRData a: as )
            content.add(a);
    }

    /**
     * lazy construction (stream-based) of a Bag
     * @param i the Iterator that generates the Bag elements
     */
    public Bag ( final BagIterator i ) {
        mode = Modes.STREAMED;
        iterator = i;
        consumed = false;
    }

    /** is the Bag stored in an ArrayList? */
    public boolean materialized () {
        return mode == Modes.MATERIALIZED;
    }

    /** is the Bag stream-based? */
    public boolean streamed () {
        return mode == Modes.STREAMED;
    }

    /** is the Bag spilled into a file? */
    public boolean spilled () {
        return mode == Modes.SPILLED;
    }

    /** return the Bag size (cache it in memory if necessary) */
    public int size () {
        if (materialized())
            return content.size();
        if (streamed() && consumed)
            throw new Error("*** The collection stream has already been consumed");
        int i = 0;
        for ( MRData e: this )
            i++;
        if (streamed())
            consumed = true;
        return i;
    }

    /** trim the ArrayList that caches the Bag */
    public void trim () {
        if (materialized())
            content.trimToSize();
    }

    /** get the n'th element of a Bag (cache it in memory if necessary)
     * @param n the index
     * @return the n'th element
     */
    public MRData get ( final int n ) {
        if (materialized())
            if (n < size())
                return content.get(n);
            else throw new Error("List index out of range: "+n);
        if (streamed() && consumed)
            throw new Error("*** The collection stream has already been consumed");
        int i = 0;
        for ( MRData e: this )
            if (i++ == n)
                return e;
        if (streamed())
            consumed = true;
        throw new Error("Cannot retrieve the "+n+"th element of a sequence");
    }

    /** replace the n'th element of a Bag with a new value
     * @param n the index
     * @param value the new value
     * @return the Bag
     */
    public Bag set ( final int n, final MRData value ) {
        if (!materialized())
            throw new Error("Cannot replace an element of a non-materialized sequence");
        content.set(n,value);
        return this;
    }

    /** add a new value to a Bag (cache it in memory if necessary)
     * @param x the new value
     */
    public void add ( final MRData x ) {
        materialize();
        if (!spilled() && Config.hadoop_mode
             && size() >= Config.max_materialized_bag)
            spill();
        if (spilled())
            try {
                if (writer == null) {   // writer was closed earlier for reading
                    FileSystem fs = FileSystem.getLocal(Plan.conf);
                    writer = SequenceFile.createWriter(fs,Plan.conf,new Path(path),
                                                       MRContainer.class,NullWritable.class,
                                                       SequenceFile.CompressionType.NONE);
                    System.err.println("*** Appending elements to a spilled Bag: "+path);
                };
                writer.append(new MRContainer(x),NullWritable.get());
            } catch (IOException e) {
                throw new Error("Cannot append an element to a spilled Bag: "+path);
            }
        else content.add(x);
    }

    /** add a new value to a Bag (cache it in memory if necessary)
     * @param x the new value
     * @return the Bag
     */
    public Bag add_element ( final MRData x ) {
        add(x);
        return this;
    }

    /** add the elements of a Bag to the end of this Bag
     * @param b the Bag whose elements are copied
     * @return the Bag
     */
    public Bag addAll ( final Bag b ) {
        for ( MRData e: b )
            add(e);
        return this;
    }

    /** make this Bag empty (cache it in memory if necessary) */
    public void clear () {
        if (materialized())
            content.clear();
        else if (streamed()) {
            if (writer != null)
                try {
                    writer.close();
                } catch (IOException ex) {
                    throw new Error(ex);
                };
            writer = null;
            path = null;
            mode = Modes.MATERIALIZED;
            content = new ArrayList<MRData>(100);
        };
        mode = Modes.MATERIALIZED;
        content = new ArrayList<MRData>();
    }

    /** cache the Bag to an ArrayList when is absolutely necessary */
    public void materialize () {
        if (materialized() || spilled())
            return;
        Iterator<MRData> iter = iterator();
        mode = Modes.MATERIALIZED;
        writer = null;
        path = null;
        content = new ArrayList<MRData>(100);
        while ( iter.hasNext() )
            add(iter.next());
        if (materialized())    // it may have been spilled
            content.trimToSize();
        iterator = null;
    }

    private static Random random_generator = new Random();

    private static String new_path ( FileSystem fs ) throws IOException {
        Path p;
        do {
            p = new Path("file://"+Config.tmpDirectory+"/mrql"+(random_generator.nextInt(1000000)));
        } while (p.getFileSystem(Plan.conf).exists(p));
        String path = p.toString();
        Plan.temporary_paths.add(path);
        return path;
    }

    /** spill the Bag to a local file */
    private void spill () {
        if (!spilled() && Config.hadoop_mode)
            try {
                if (Plan.conf == null)
                    Plan.conf = Evaluator.evaluator.new_configuration();
                final FileSystem fs = FileSystem.getLocal(Plan.conf);
                path = new_path(fs);
                System.err.println("*** Spilling a Bag to a local file: "+path);
                final Path p = new Path(path);
                writer = SequenceFile.createWriter(fs,Plan.conf,new Path(path),
                                                   MRContainer.class,NullWritable.class,
                                                   SequenceFile.CompressionType.NONE);
                for ( MRData e: this )
                    writer.append(new MRContainer(e),NullWritable.get());
                mode = Modes.SPILLED;
                content = null;
                iterator = null;
            } catch (Exception e) {
                throw new Error("Cannot spill a Bag to a local file");
            }
    }

    /**
     * sort the Bag (cache it in memory if necessary).
     * If the Bag was spilled during caching, use external sorting
     */
    public void sort () {
        materialize();
        if (spilled())  // if it was spilled during materialize()
            try {       // use external sorting
                if (writer != null)
                    writer.close();
                FileSystem fs = FileSystem.getLocal(Plan.conf);
                SequenceFile.Sorter sorter
                    = new SequenceFile.Sorter(fs,new Plan.MRContainerKeyComparator(),
                                              MRContainer.class,NullWritable.class,Plan.conf);
                String out_path = new_path(fs);
                System.err.println("*** Using external sorting on a spilled bag "+path+" -> "+out_path);
                sorter.setMemory(64*1024*1024);
                sorter.sort(new Path(path),new Path(out_path));
                path = out_path;
                writer = null;
            } catch (Exception ex) {
                throw new Error("Cannot sort a spilled bag");
            }
        else Collections.sort(content);
    }

    /** return the Bag Iterator */
    public Iterator<MRData> iterator () {
        if (spilled())
            try {
                if (writer != null)
                    writer.close();
                writer = null;
                return new BagIterator () {
                    final FileSystem fs = FileSystem.getLocal(Plan.conf);
                    final SequenceFile.Reader reader = new SequenceFile.Reader(fs,new Path(path),Plan.conf);
                    final MRContainer key = new MRContainer();
                    final NullWritable value = NullWritable.get();
                    MRData data;
                    public boolean hasNext () {
                        try {
                            if (!reader.next(key,value)) {
                                reader.close();
                                return false;
                            };
                            data = key.data();
                            return true;
                        } catch (IOException e) {
                            throw new Error("Cannot collect values from a spilled Bag");
                        }
                    }
                    public MRData next () {
                        return data;
                    }
                };
            } catch (IOException e) {
                throw new Error("Cannot collect values from a spilled Bag");
            }
        else if (materialized())
            return content.iterator();
        else {
            if (consumed)  // this should never happen
                throw new Error("*** The collection stream has already been consumed");
            consumed = true;
            return iterator;
        }
    }

    /** cache MRData in memory by caching all Bags at any place and depth in MRData */
    public void materializeAll () {
        materialize();
        for (MRData e: this)
            e.materializeAll();
    }

    /** concatenate the elements of a given Bag to the elements of this Bag.
     * Does not change either Bag
     * @param s the given Bag
     * @return a new Bag
     */
    public Bag union ( final Bag s ) {
        final Iterator<MRData> i1 = iterator();
        final Iterator<MRData> i2 = s.iterator();
        return new Bag(new BagIterator () {
                boolean first = true;
                public boolean hasNext () {
                    if (first)
                        if (i1.hasNext())
                            return true;
                        else {
                            first = false;
                            return i2.hasNext();
                        }
                    else return i2.hasNext();
                }
                public MRData next () {
                    if (first)
                        return i1.next();
                    else return i2.next();
                }
            });
    }

    /** does this Bag contain an element?
     * Cache this Bag in memory befor tetsing if necessary
     * @param x the element to find
     */
    public boolean contains ( final MRData x ) {
        if (materialized())
            return content.contains(x);
        if (streamed() && consumed)
            throw new Error("*** The collection stream has already been consumed");
        for ( MRData e: this )
            if (x.equals(e))
                return true;
        if (streamed())
            consumed = true;
        return false;
    }

    /** if this Bag is a Map from keys to values (a Bag of (key,value) pairs),
     * find the value with the given key; raise an error if not found
     * @param key the search key
     * @return the value associated with the key
     */
    public MRData map_find ( final MRData key ) {
        if (streamed() && consumed)
            throw new Error("*** The collection stream has already been consumed");
        for ( MRData e: this ) {
            Tuple p = (Tuple) e;
            if (key.equals(p.first()))
                return p.second();
        };
        if (streamed())
            consumed = true;
        throw new Error("key "+key+" not found in map");
    }

    /** if this Bag is a Map from keys to values (a Bag of (key,value) pairs),
     * does it contain a given key?
     * @param key the search key
     */
    public boolean map_contains ( final MRData key ) {
        if (streamed() && consumed)
            throw new Error("*** The collection stream has already been consumed");
        for ( MRData e: this )
            if (key.equals(((Tuple)e).first()))
                return true;
        if (streamed())
            consumed = true;
        return false;
    }

    /** the output serializer for Bag.
     * Stream-based Bags are serialized lazily (without having to cache the Bag in memory)
     */
    final public void write ( DataOutput out ) throws IOException {
        if (materialized()) {
            out.writeByte(MRContainer.BAG);
            WritableUtils.writeVInt(out,size());
            for ( MRData e: this )
                e.write(out);
        } else {
            out.writeByte(MRContainer.LAZY_BAG);
            for ( MRData e: this )
                e.write(out);
            out.writeByte(MRContainer.END_OF_LAZY_BAG);
        }
    }

    /** the input serializer for Bag */
    final public static Bag read ( DataInput in ) throws IOException {
        int n = WritableUtils.readVInt(in);
        Bag bag = new Bag(n);
        for ( int i = 0; i < n; i++ )
            bag.add(MRContainer.read(in));
        return bag;
    }

    /** a lazy input serializer for a Bag (it doesn't need to cache a Bag in memory) */
    public static Bag lazy_read ( final DataInput in ) throws IOException {
        Bag bag = new Bag(100);
        MRData data = MRContainer.read(in);
        while (data != MRContainer.end_of_lazy_bag) {
            bag.add(data);
            data = MRContainer.read(in);
        };
        if (bag.materialized())
            bag.content.trimToSize();
        return bag;
    }

    /** the input serializer for Bag */
    public void readFields ( DataInput in ) throws IOException {
        int n = WritableUtils.readVInt(in);
        mode = Modes.MATERIALIZED;
        iterator = null;
        path = null;
        writer = null;
        if (content == null)
            content = new ArrayList<MRData>(n);
        else {
            content.clear();
            content.ensureCapacity(n);
        };
        for ( int i = 0; i < n; i++ )
            add(MRContainer.read(in));
    }

    private void writeObject ( ObjectOutputStream out ) throws IOException {
        materialize();
        WritableUtils.writeVInt(out,size());
        for ( MRData e: this )
            e.write(out);
    }

    private void readObject ( ObjectInputStream in ) throws IOException, ClassNotFoundException {
        int n = WritableUtils.readVInt(in);
        mode = Modes.MATERIALIZED;
        iterator = null;
        path = null;
        writer = null;
        content = new ArrayList<MRData>(n);
        for ( int i = 0; i < n; i++ )
            add(MRContainer.read(in));
    }

    private void readObjectNoData () throws ObjectStreamException { };

    /** compare this Bag with a given Bag by comparing their associated elements */
    public int compareTo ( MRData x ) {
        Bag xt = (Bag)x;
        Iterator<MRData> xi = xt.iterator();
        Iterator<MRData> yi = iterator();
        while ( xi.hasNext() && yi.hasNext() ) {
            int c = xi.next().compareTo(yi.next());
            if (c < 0)
                return -1;
            else if (c > 0)
                return 1;
        };
        if (xi.hasNext())
            return -1;
        else if (yi.hasNext())
            return 1;
        else return 0;
    }

    /** compare this Bag with a given Bag by comparing their associated elements */
    final public static int compare ( byte[] x, int xs, int xl, byte[] y, int ys, int yl, int[] size ) {
        try {
            int xn = WritableComparator.readVInt(x,xs);
            int xx = WritableUtils.decodeVIntSize(x[xs]);
            int yn = WritableComparator.readVInt(y,ys);
            int yy = WritableUtils.decodeVIntSize(y[ys]);
            for ( int i = 0; i < xn && i < yn; i++ ) {
                int k = MRContainer.compare(x,xs+xx,xl-xx,y,ys+yy,yl-yy,size);
                if (k != 0)
                    return k;
                xx += size[0];
                yy += size[0];
            };
            size[0] = xx+1;
            if (xn > yn)
                return 1;
            if (xn < yn)
                return -1;
            return 0;
        } catch (IOException e) {
            throw new Error(e);
        }
    }

    /** is this Bag equal to another Bag (order is important) */
    public boolean equals ( Object x ) {
        if (!(x instanceof Bag))
            return false;
        Bag xt = (Bag) x;
        Iterator<MRData> xi = xt.iterator();
        Iterator<MRData> yi = iterator();
        while ( xi.hasNext() && yi.hasNext() )
            if ( !xi.next().equals(yi.next()) )
                return false;
        return xi.hasNext() || yi.hasNext();
    }

    /** the hash code of this Bag is the XOR of the hash code of its elements */
    public int hashCode () {
        int h = 127;
        for ( MRData e: this )
            h ^= e.hashCode();
        return Math.abs(h);
    }

    /** show the first few Bag elements (controlled by -bag_print) */
    public String toString () {
        materialize();
        StringBuffer b = new StringBuffer("{ ");
        int i = 0;
        for ( MRData e: this )
            if ( i++ < Config.max_bag_size_print || Config.max_bag_size_print < 0 )
                b.append(((i>1)?", ":"")+e);
            else return b.append(", ... }").toString();
        return b.append(" }").toString();
    }
}
