/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2002 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowlegement:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 *
 * 4. The names "The Jakarta Project", "Ant", and "Apache Software
 *    Foundation" must not be used to endorse or promote products derived
 *    from this software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache"
 *    nor may "Apache" appear in their names without prior written
 *    permission of the Apache Group.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
package org.apache.tools.ant.taskdefs.optional.clearcase;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Enumeration;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.util.regexp.RegexpMatcher;
import org.apache.tools.ant.util.regexp.RegexpMatcherFactory;
import org.apache.tools.ant.util.StringUtils;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.taskdefs.Execute;
import org.apache.tools.ant.taskdefs.ExecuteStreamHandler;
import org.apache.tools.ant.taskdefs.PumpStreamHandler;

/**
 * Helper methods related to clearcase commands.
 *
 * @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a>
 */
public final class CCUtils {

    public final static String DEFAULT_COMMENT = "\"Automatic operation from Jakarta Ant\"";

    private final static RegexpMatcherFactory __reFactory = new RegexpMatcherFactory();

    /** the matchers cache: pattern/matcher */
    private final static Hashtable matchers = new Hashtable();

    private Task task;

    public CCUtils(Task task){
        this.task = task;
    }

    /**
     * return a group of matches of a given RE in a string.
     * @param pattern the pattern to match in the input data.
     * @param input the data where to look for the pattern.
     * @return the group of matches if any, 0 being the full match
     * and the rest being parenthesized expressions. <tt>null</tt>
     * if there are no matches.
     */
    public Vector matches(String pattern, String input){
        RegexpMatcher matcher = (RegexpMatcher)matchers.get(pattern);
        if (matcher == null){
            matcher = __reFactory.newRegexpMatcher();
            matcher.setPattern(pattern);
            matchers.put(pattern, matcher);
        }
        return matcher.getGroups(input);
    }

    /**
     * Try to resolve a symbolic link if it is one.
     * @param toresolve the symbolic link to resolve.
     * @return the resolved link if it is a symbolic link, otherwise
     * return the original link.
     */
    public File resolveSymbolicLink(File toresolve) throws Exception {
        String[] args = { "ls", "-l", toresolve.getAbsolutePath() };
        CmdResult res = cleartool(args);
        if (res.getStatus() != 0 ){
            throw new BuildException(res.getStdErr());
        }
        Vector groups = matches("symbolic link(.*)-->(.*)", res.getStdout());
        if (groups == null){
            return toresolve; // or null ?
        }
        String path = (String)groups.elementAt(2);
        path = path.trim();
        File resolved = new File(path);
        if ( !resolved.isAbsolute() ){
            resolved = new File(toresolve.getParent(), path);
        }
        return resolved;
    }

    /**
     * Move a file to another. (ie rename)
     */
    public void move(File from, File to) throws Exception {
        String[] args = {"move", "-nc", from.getPath(), to.getPath()};
        CmdResult res = cleartool(args);
        if (res.getStatus() != 0) {
            throw new BuildException(res.getStdErr());
        }
    }

    /**
     * return the list of checkedout files in a given viewpath.
     * @param viewpath the path to the view/directory to look for
     * checkedout files.
     * @param recurse <tt>true</tt> to look for files recursively,
     * otherwise <tt>false</tt>
     * @return the list of checkedout files in the view (full pathname).
     */
    public Hashtable lsco(File viewpath, boolean recurse) {
        String recurseParam = recurse ? "-r" : "";
        String fullpath = viewpath.getAbsolutePath();
        //@fixme is -cvi conflicting with -r ?
        String[] args = {"lsco", recurseParam, "-cvi", "-s", "-me", fullpath};
        CmdResult res = cleartool(args);
        if (res.getStatus() != 0) {
            throw new BuildException(res.getStdErr());
        }

        Vector lines = res.getStdoutLines();
        Hashtable map = toFiles(lines);
        return map;
    }

    /**
     * Transform a set of paths into canonical paths.
     * Typically this should be used to transform a set of
     * output lines by cleartool representing file paths.
     */
    public static Hashtable toFiles(Vector paths){
        Hashtable map = new Hashtable();
        for (int i = 0; i < paths.size(); i++) {
            String path = (String) paths.elementAt(i);
            try {
                // the path is normally the full path, we normally
                // not need to do a new File(viewpath, path)
                File f = new File(path);
                path = f.getCanonicalPath();
                map.put(path, path);
            } catch (IOException e) {
                // assume it's not a file...
            }
        }
        return map;
    }

    /**
     * Returns the list of files that are *not* checked out.
     * @see #lsco(File, boolean)
     */
    public Hashtable lsnco(File viewpath){
        String[] args = {"find", viewpath.getAbsolutePath(), "-type", "f", "-cvi", "-nxn", "-print"};
        CmdResult res = cleartool(args);
        Vector lines = res.getStdoutLines();
        Hashtable all = toFiles(lines);
        Hashtable co = lsco(viewpath, true);
        // remove the co files
        Enumeration keys = co.keys();
        while ( keys.hasMoreElements() ){
            Object path = keys.nextElement();
            Object o = all.remove(path);
            if (o == null){
                // oops how come a co file is not found by find ?
            }
        }
        return all;
    }

    /** returns the list of private files in the view */
    public Hashtable lsprivate(File viewpath){
        // for a snapshot view, we must use ls -r -view_only
        return null;
    }

    public void checkin(File file){
        String[] args = {"ci", "-nc", "-identical", file.getAbsolutePath()} ;
        CmdResult res = cleartool(args);
        if (res.getStatus() != 0){
            throw new BuildException(res.getStdErr());
        }
    }

    public void checkout(File file){
        String[] args = {"co", "-nc", "-unreserved", file.getAbsolutePath()} ;
        CmdResult res = cleartool(args);
        if (res.getStatus() != 0){
            throw new BuildException(res.getStdErr());
        }
    }

    public void uncheckout(File file){
        String[] args = {"unco", "-rm", file.getAbsolutePath() };
        CmdResult res = cleartool(args);
        if (res.getStatus() != 0){
            throw new BuildException(res.getStdErr());
        }
    }

    /**
     * Helper method to execute a given cleartool command.
     * @param args the parameters used to execute cleartool.
     * @return the result of the command.
     */
    public static CmdResult cleartool(String[] args) {
        String[] nargs = new String[args.length + 1];
        nargs[0] = "cleartool";
        System.arraycopy(args, 0, nargs, 1, args.length);

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ByteArrayOutputStream err = new ByteArrayOutputStream();
        ExecuteStreamHandler handler = new PumpStreamHandler(out, err);
        Execute exe = new Execute(handler);
        exe.setCommandline(nargs);
        try {
            int retcode = exe.execute();
            return new CmdResult(retcode, out.toString(), err.toString());
        } catch (IOException e){
            throw new BuildException(e);
        }
    }

    /**
     * Create the comment file used by cleartool commands.
     */
    public static File createCommentFile(String comment) {
        FileUtils futils = FileUtils.newFileUtils();
        File f = futils.createTempFile("ant_cc", ".tmp", new File("."));
        Writer writer = null;
        try {
            writer = new BufferedWriter(new FileWriter(f));
            writer.write(comment);
            writer.flush();
        } catch (IOException e){
            throw new BuildException(e);
        } finally {
            if (writer != null){
                try {
                    writer.close();
                } catch (IOException e){
                }
            }
        }
        return f;
    }

}
