/*
 *  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.tools.ant.taskdefs;

import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.Vector;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.FileList;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Mapper;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.ResourceCollection;
import org.apache.tools.ant.types.resources.FileProvider;
import org.apache.tools.ant.types.resources.FileResource;
import org.apache.tools.ant.types.resources.Touchable;
import org.apache.tools.ant.types.resources.Union;
import org.apache.tools.ant.util.FileNameMapper;
import org.apache.tools.ant.util.FileUtils;

/**
 * Touch a file and/or fileset(s) and/or filelist(s);
 * corresponds to the Unix touch command.
 *
 * <p>If the file to touch doesn't exist, an empty one is created.</p>
 *
 * @since Ant 1.1
 *
 * @ant.task category="filesystem"
 */
public class Touch extends Task {

    public interface DateFormatFactory {
        DateFormat getPrimaryFormat();
        DateFormat getFallbackFormat();
    }

    public static final DateFormatFactory DEFAULT_DF_FACTORY
        = new DateFormatFactory() {

        private ThreadLocal<DateFormat> primary =
            new ThreadLocal<DateFormat>() {
                @Override
                protected DateFormat initialValue() {
                    return new SimpleDateFormat("MM/dd/yyyy hh:mm a",
                                                Locale.US);
                }
            };
        private ThreadLocal<DateFormat> fallback =
            new ThreadLocal<DateFormat>() {
                @Override
                protected DateFormat initialValue() {
                    return new SimpleDateFormat("MM/dd/yyyy hh:mm:ss a",
                                                Locale.US);
                }
            };

        public DateFormat getPrimaryFormat() {
            return primary.get();
        }
        public DateFormat getFallbackFormat() {
            return fallback.get();
        }
    };
    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();

    private File file;
    private long millis = -1;
    private String dateTime;
    private Vector filesets = new Vector();
    private Union resources;
    private boolean dateTimeConfigured;
    private boolean mkdirs;
    private boolean verbose = true;
    private FileNameMapper fileNameMapper = null;
    private DateFormatFactory dfFactory = DEFAULT_DF_FACTORY;

    /**
     * Construct a new <code>Touch</code> task.
     */
    public Touch() {
    }

    /**
     * Sets a single source file to touch.  If the file does not exist
     * an empty file will be created.
     * @param file the <code>File</code> to touch.
     */
    public void setFile(File file) {
        this.file = file;
    }

    /**
     * Set the new modification time of file(s) touched
     * in milliseconds since midnight Jan 1 1970. Optional, default=now.
     * @param millis the <code>long</code> timestamp to use.
     */
    public void setMillis(long millis) {
        this.millis = millis;
    }

    /**
     * Set the new modification time of file(s) touched
     * in the format &quot;MM/DD/YYYY HH:MM AM <i>or</i> PM&quot;
     * or &quot;MM/DD/YYYY HH:MM:SS AM <i>or</i> PM&quot;.
     * Optional, default=now.
     * @param dateTime the <code>String</code> date in the specified format.
     */
    public void setDatetime(String dateTime) {
        if (this.dateTime != null) {
            log("Resetting datetime attribute to " + dateTime, Project.MSG_VERBOSE);
        }
        this.dateTime = dateTime;
        dateTimeConfigured = false;
    }

    /**
     * Set whether nonexistent parent directories should be created
     * when touching new files.
     * @param mkdirs <code>boolean</code> whether to create parent directories.
     * @since Ant 1.6.3
     */
    public void setMkdirs(boolean mkdirs) {
        this.mkdirs = mkdirs;
    }

    /**
     * Set whether the touch task will report every file it creates;
     * defaults to <code>true</code>.
     * @param verbose <code>boolean</code> flag.
     * @since Ant 1.6.3
     */
    public void setVerbose(boolean verbose) {
        this.verbose = verbose;
    }

    /**
     * Set the format of the datetime attribute.
     * @param pattern the <code>SimpleDateFormat</code>-compatible format pattern.
     * @since Ant 1.6.3
     */
    public void setPattern(final String pattern) {
        dfFactory = new DateFormatFactory() {
            public DateFormat getPrimaryFormat() {
                return new SimpleDateFormat(pattern);
            }
            public DateFormat getFallbackFormat() {
                return null;
            }
        };
    }

    /**
     * Add a <code>Mapper</code>.
     * @param mapper the <code>Mapper</code> to add.
     * @since Ant 1.6.3
     */
    public void addConfiguredMapper(Mapper mapper) {
        add(mapper.getImplementation());
    }

    /**
     * Add a <code>FileNameMapper</code>.
     * @param fileNameMapper the <code>FileNameMapper</code> to add.
     * @since Ant 1.6.3
     * @throws BuildException if multiple mappers are added.
     */
    public void add(FileNameMapper fileNameMapper) throws BuildException {
        if (this.fileNameMapper != null) {
            throw new BuildException("Only one mapper may be added to the "
                + getTaskName() + " task.");
        }
        this.fileNameMapper = fileNameMapper;
    }

    /**
     * Add a set of files to touch.
     * @param set the <code>Fileset</code> to add.
     */
    public void addFileset(FileSet set) {
        filesets.add(set);
        add(set);
    }

    /**
     * Add a filelist to touch.
     * @param list the <code>Filelist</code> to add.
     */
    public void addFilelist(FileList list) {
        add(list);
    }

    /**
     * Add a collection of resources to touch.
     * @param rc the collection to add.
     * @since Ant 1.7
     */
    public synchronized void add(ResourceCollection rc) {
        resources = resources == null ? new Union() : resources;
        resources.add(rc);
    }

    /**
     * Check that this task has been configured properly.
     * @throws BuildException if configuration errors are detected.
     * @since Ant 1.6.3
     */
    protected synchronized void checkConfiguration() throws BuildException {
        if (file == null && resources == null) {
            throw new BuildException("Specify at least one source"
                                   + "--a file or resource collection.");
        }
        if (file != null && file.exists() && file.isDirectory()) {
            throw new BuildException("Use a resource collection to touch directories.");
        }
        if (dateTime != null && !dateTimeConfigured) {
            long workmillis = millis;
            if ("now".equalsIgnoreCase(dateTime)) {
                workmillis = System.currentTimeMillis();
            } else {
                DateFormat df = dfFactory.getPrimaryFormat();
                ParseException pe = null;
                try {
                    workmillis = df.parse(dateTime).getTime();
                } catch (ParseException peOne) {
                    df = dfFactory.getFallbackFormat();
                    if (df == null) {
                        pe = peOne;
                    } else {
                        try {
                            workmillis = df.parse(dateTime).getTime();
                        } catch (ParseException peTwo) {
                            pe = peTwo;
                        }
                    }
                }
                if (pe != null) {
                    throw new BuildException(pe.getMessage(), pe, getLocation());
                }
                if (workmillis < 0) {
                    throw new BuildException("Date of " + dateTime
                            + " results in negative " + "milliseconds value "
                            + "relative to epoch " + "(January 1, 1970, "
                            + "00:00:00 GMT).");
                }
            }
            log("Setting millis to " + workmillis + " from datetime attribute",
                    ((millis < 0) ? Project.MSG_DEBUG : Project.MSG_VERBOSE));
            setMillis(workmillis);
            // only set if successful to this point:
            dateTimeConfigured = true;
        }
    }

    /**
     * Execute the touch operation.
     *
     * @throws BuildException
     *             if an error occurs.
     */
    public void execute() throws BuildException {
        checkConfiguration();
        touch();
    }

    /**
     * Does the actual work; assumes everything has been checked by now.
     * @throws BuildException if an error occurs.
     */
    protected void touch() throws BuildException {
        long defaultTimestamp = getTimestamp();

        if (file != null) {
            touch(new FileResource(file.getParentFile(), file.getName()),
                  defaultTimestamp);
        }
        if (resources == null) {
            return;
        }
        // deal with the resource collections
        for (Resource r : resources) {
            Touchable t = r.as(Touchable.class);
            if (t == null) {
                throw new BuildException("Can't touch " + r);
            }
            touch(r, defaultTimestamp);
        }

        // deal with filesets in a special way since the task
        // originally also used the directories and Union won't return
        // them.
        final int size = filesets.size();
        for (int i = 0; i < size; i++) {
            FileSet fs = (FileSet) filesets.elementAt(i);
            DirectoryScanner ds = fs.getDirectoryScanner(getProject());
            File fromDir = fs.getDir(getProject());

            String[] srcDirs = ds.getIncludedDirectories();

            for (int j = 0; j < srcDirs.length; j++) {
                touch(new FileResource(fromDir, srcDirs[j]), defaultTimestamp);
            }
        }
    }

    /**
     * Touch a single file with the current timestamp (this.millis). This method
     * does not interact with any nested mappers and remains for reasons of
     * backwards-compatibility only.
     * @param file file to touch
     * @throws BuildException on error
     * @deprecated since 1.6.x.
     */
    protected void touch(File file) {
        touch(file, getTimestamp());
    }

    private long getTimestamp() {
        return (millis < 0) ? System.currentTimeMillis() : millis;
    }

    private void touch(Resource r, long defaultTimestamp) {
        if (fileNameMapper == null) {
            FileProvider fp = r.as(FileProvider.class);
            if (fp != null) {
                // use this to create file and deal with non-writable files
                touch(fp.getFile(), defaultTimestamp);
            } else {
                r.as(Touchable.class).touch(defaultTimestamp);
            }
        } else {
            String[] mapped = fileNameMapper.mapFileName(r.getName());
            if (mapped != null && mapped.length > 0) {
                long modTime = defaultTimestamp;
                if (millis < 0 && r.isExists()) {
                    modTime = r.getLastModified();
                }
                for (int i = 0; i < mapped.length; i++) {
                    touch(getProject().resolveFile(mapped[i]), modTime);
                }
            }
        }
    }

    private void touch(File file, long modTime) {
        if (!file.exists()) {
            log("Creating " + file,
                ((verbose) ? Project.MSG_INFO : Project.MSG_VERBOSE));
            try {
                FILE_UTILS.createNewFile(file, mkdirs);
            } catch (IOException ioe) {
                throw new BuildException("Could not create " + file, ioe,
                                         getLocation());
            }
        }
        if (!file.canWrite()) {
            throw new BuildException("Can not change modification date of "
                                     + "read-only file " + file);
        }
        FILE_UTILS.setFileLastModified(file, modTime);
    }

}
