/*
 *  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.ant.compress.resources;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.ArchiveFileSet;
import org.apache.tools.ant.types.DataType;
import org.apache.tools.ant.types.Reference;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.ResourceCollection;
import org.apache.tools.ant.types.resources.Union;
import org.apache.tools.ant.util.CollectionUtils;

/**
 * A resource collection that treats all nested resources as archives
 * and returns the contents of the archives as its content.
 */
public class Archives extends DataType
    implements ResourceCollection, Cloneable {

    private Union zips = new Union();
    private Union tars = new Union();
    private Union ars = new Union();
    private Union cpios = new Union();
    private Union arjs = new Union();
    private Union dumps = new Union();
    private Union sevenzs = new Union();

    /**
     * Wrapper to identify nested resource collections as ZIP
     * archives.
     */
    public Union createZips() {
        if (isReference()) {
            throw noChildrenAllowed();
        }
        setChecked(false);
        return zips;
    }

    /**
     * Wrapper to identify nested resource collections as ZIP
     * archives.
     */
    public Union createTars() {
        if (isReference()) {
            throw noChildrenAllowed();
        }
        setChecked(false);
        return tars;
    }

    /**
     * Wrapper to identify nested resource collections as AR
     * archives.
     */
    public Union createArs() {
        if (isReference()) {
            throw noChildrenAllowed();
        }
        setChecked(false);
        return ars;
    }

    /**
     * Wrapper to identify nested resource collections as ARJ
     * archives.
     * @since Apache Compress Antlib 1.5
     */
    public Union createArjs() {
        if (isReference()) {
            throw noChildrenAllowed();
        }
        setChecked(false);
        return arjs;
    }

    /**
     * Wrapper to identify nested resource collections as CPIO
     * archives.
     */
    public Union createCpios() {
        if (isReference()) {
            throw noChildrenAllowed();
        }
        setChecked(false);
        return cpios;
    }

    /**
     * Wrapper to identify nested resource collections as Unix dump
     * archives.
     * @since Apache Compress Antlib 1.5
     */
    public Union createDumps() {
        if (isReference()) {
            throw noChildrenAllowed();
        }
        setChecked(false);
        return dumps;
    }

    /**
     * Wrapper to identify nested resource collections as 7z
     * archives.
     * @since Apache Compress Antlib 1.5
     */
    public Union createSevenzs() {
        if (isReference()) {
            throw noChildrenAllowed();
        }
        setChecked(false);
        return sevenzs;
    }

    /**
     * Sums the sizes of nested archives.
     */
    @Override
    public int size() {
        if (isReference()) {
            return ((Archives) getCheckedRef()).size();
        }
        dieOnCircularReference();
        int total = 0;
        for (Iterator i = grabArchives(); i.hasNext(); ) {
            total += ((ResourceCollection) i.next()).size();
        }
        return total;
    }

    /**
     * Merges the nested collections.
     */
    @Override
    public Iterator iterator() {
        if (isReference()) {
            return ((Archives) getCheckedRef()).iterator();
        }
        dieOnCircularReference();
        List l = new LinkedList();
        for (Iterator i = grabArchives(); i.hasNext(); ) {
            l.addAll(CollectionUtils
                     .asCollection(((ResourceCollection) i.next()).iterator()));
        }
        return l.iterator();
    }

    /**
     * @return false
     */
    @Override
    public boolean isFilesystemOnly() {
        if (isReference()) {
            return ((Archives) getCheckedRef()).isFilesystemOnly();
        }
        dieOnCircularReference();
        return false;
    }

    /**
     * Overrides the base version.
     * @param r the Reference to set.
     */
    @Override
    public void setRefid(Reference r) {
        if (zips.getResourceCollections().size() > 0
            || ars.getResourceCollections().size() > 0
            || cpios.getResourceCollections().size() > 0
            || arjs.getResourceCollections().size() > 0
            || dumps.getResourceCollections().size() > 0
            || sevenzs.getResourceCollections().size() > 0
            || tars.getResourceCollections().size() > 0) {
            throw tooManyAttributes();
        }
        super.setRefid(r);
    }

    /**
     * Implement clone.  The nested resource collections are cloned as
     * well.
     * @return a cloned instance.
     */
    @Override
    public Object clone() {
        try {
            Archives a = (Archives) super.clone();
            a.zips = (Union) zips.clone();
            a.tars = (Union) tars.clone();
            a.ars = (Union) ars.clone();
            a.cpios = (Union) cpios.clone();
            a.arjs = (Union) arjs.clone();
            a.dumps = (Union) dumps.clone();
            a.sevenzs = (Union) sevenzs.clone();
            return a;
        } catch (CloneNotSupportedException e) {
            throw new BuildException(e);
        }
    }

    // TODO this is a pretty expensive operation and so the result
    // should be cached.
    /**
     * Turns all nested resources into corresponding ArchiveFileSets
     * and returns an iterator over the collected archives.
     */
    protected Iterator/*<ArchiveFileset>*/ grabArchives() {
        List l = new LinkedList();
        for (Iterator iter = zips.iterator(); iter.hasNext(); ) {
            l.add(configureArchive(new ZipFileSet(),
                                   (Resource) iter.next()));
        }
        for (Iterator iter = tars.iterator(); iter.hasNext(); ) {
            l.add(configureArchive(new TarFileSet(),
                                   (Resource) iter.next()));
        }
        for (Iterator iter = ars.iterator(); iter.hasNext(); ) {
            l.add(configureArchive(new ArFileSet(),
                                   (Resource) iter.next()));
        }
        for (Iterator iter = cpios.iterator(); iter.hasNext(); ) {
            l.add(configureArchive(new CpioFileSet(),
                                   (Resource) iter.next()));
        }
        for (Iterator iter = arjs.iterator(); iter.hasNext(); ) {
            l.add(configureArchive(new ArjFileSet(),
                                   (Resource) iter.next()));
        }
        for (Iterator iter = dumps.iterator(); iter.hasNext(); ) {
            l.add(configureArchive(new DumpFileSet(),
                                   (Resource) iter.next()));
        }
        for (Iterator iter = sevenzs.iterator(); iter.hasNext(); ) {
            l.add(configureArchive(new SevenZFileSet(),
                                   (Resource) iter.next()));
        }
        return l.iterator();
    }

    /**
     * Configures the archivefileset based on this type's settings,
     * set the source.
     */
    protected ArchiveFileSet configureArchive(ArchiveFileSet afs,
                                              Resource src) {
        afs.setProject(getProject());
        afs.setSrcResource(src);
        return afs;
    }

    /**
     * Overrides the version of DataType to recurse on all DataType
     * child elements that may have been added.
     * @param stk the stack of data types to use (recursively).
     * @param p   the project to use to dereference the references.
     * @throws BuildException on error.
     */
    @Override
    protected synchronized void dieOnCircularReference(Stack stk, Project p)
        throws BuildException {
        if (isChecked()) {
            return;
        }
        if (isReference()) {
            super.dieOnCircularReference(stk, p);
        } else {
            pushAndInvokeCircularReferenceCheck(zips, stk, p);
            pushAndInvokeCircularReferenceCheck(tars, stk, p);
            pushAndInvokeCircularReferenceCheck(ars, stk, p);
            pushAndInvokeCircularReferenceCheck(cpios, stk, p);
            pushAndInvokeCircularReferenceCheck(arjs, stk, p);
            pushAndInvokeCircularReferenceCheck(dumps, stk, p);
            pushAndInvokeCircularReferenceCheck(sevenzs, stk, p);
            setChecked(true);
        }
    }

}
