/*
 * 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.commons.vfs.tasks;

import org.apache.commons.vfs.FileName;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileType;
import org.apache.commons.vfs.NameScope;
import org.apache.commons.vfs.Selectors;
import org.apache.commons.vfs.util.Messages;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;

/**
 * An abstract file synchronization task.  Scans a set of source files and
 * folders, and a destination folder, and performs actions on missing and
 * out-of-date files.  Specifically, performs actions on the following:
 * <ul>
 * <li>Missing destination file.
 * <li>Missing source file.
 * <li>Out-of-date destination file.
 * <li>Up-to-date destination file.
 * </ul>
 *
 * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
 * @version $Revision$ $Date$
 * @todo Deal with case where dest file maps to a child of one of the source files
 * @todo Deal with case where dest file already exists and is incorrect type (not file, not a folder)
 * @todo Use visitors
 * @todo Add default excludes
 * @todo Allow selector, mapper, filters, etc to be specified.
 * @todo Handle source/dest directories as well
 * @todo Allow selector to be specified for choosing which dest files to sync
 */
public abstract class AbstractSyncTask
    extends VfsTask
{
    private final ArrayList srcFiles = new ArrayList();
    private String destFileUrl;
    private String destDirUrl;
    private String srcDirUrl;
    private boolean srcDirIsBase;
    private boolean failonerror = true;
    private String filesList;

    /**
     * Sets the destination file.
     * @param destFile The destination file name.
     */
    public void setDestFile(final String destFile)
    {
        this.destFileUrl = destFile;
    }

    /**
     * Sets the destination directory.
     * @param destDir The destination directory.
     */
    public void setDestDir(final String destDir)
    {
        this.destDirUrl = destDir;
    }

    /**
     * Sets the source file.
     * @param srcFile The source file name.
     */
    public void setSrc(final String srcFile)
    {
        final SourceInfo src = new SourceInfo();
        src.setFile(srcFile);
        addConfiguredSrc(src);
    }

    /**
     * Sets the source directory.
     * @param srcDir The source directory.
     */
    public void setSrcDir(final String srcDir)
    {
        this.srcDirUrl = srcDir;
    }

    /**
     * Sets whether the source directory should be consider as the base directory.
     * @param srcDirIsBase true if the source directory is the base directory.
     */
    public void setSrcDirIsBase(final boolean srcDirIsBase)
    {
        this.srcDirIsBase = srcDirIsBase;
    }

    /**
     * Sets whether we should fail if there was an error or not.
     * @param failonerror true if the operation should fail if there is an error.
     */
    public void setFailonerror(final boolean failonerror)
    {
        this.failonerror = failonerror;
    }

    /**
     * Sets whether we should fail if there was an error or not.
     * @return true if the operation should fail if there was an error.
     */
    public boolean isFailonerror()
    {
        return failonerror;
    }

    /**
     * Sets the files to includes.
     * @param filesList The list of files to include.
     */
    public void setIncludes(final String filesList)
    {
        this.filesList = filesList;
    }

    /**
     * Adds a nested &lt;src&gt; element.
     * @param srcInfo A nested source element.
     * @throws BuildException if the SourceInfo doesn't reference a file.
     */
    public void addConfiguredSrc(final SourceInfo srcInfo)
        throws BuildException
    {
        if (srcInfo.file == null)
        {
            final String message = Messages.getString("vfs.tasks/sync.no-source-file.error");
            throw new BuildException(message);
        }
        srcFiles.add(srcInfo);
    }

    /**
     * Executes this task.
     * @throws BuildException if an error occurs.
     */
    public void execute() throws BuildException
    {
        // Validate
        if (destFileUrl == null && destDirUrl == null)
        {
            final String message =
                Messages.getString("vfs.tasks/sync.no-destination.error");
            logOrDie(message, Project.MSG_WARN);
            return;
        }

        if (destFileUrl != null && destDirUrl != null)
        {
            final String message =
                Messages.getString("vfs.tasks/sync.too-many-destinations.error");
            logOrDie(message, Project.MSG_WARN);
            return;
        }

        // Add the files of the includes attribute to the list
        if (srcDirUrl != null && !srcDirUrl.equals(destDirUrl) && filesList != null && filesList.length() > 0)
        {
            if (!srcDirUrl.endsWith("/"))
            {
                srcDirUrl += "/";
            }
            StringTokenizer tok = new StringTokenizer(filesList, ", \t\n\r\f", false);
            while (tok.hasMoreTokens())
            {
                String nextFile = tok.nextToken();

                // Basic compatibility with Ant fileset for directories
                if (nextFile.endsWith("/**"))
                {
                    nextFile = nextFile.substring(0, nextFile.length() - 2);
                }

                final SourceInfo src = new SourceInfo();
                src.setFile(srcDirUrl + nextFile);
                addConfiguredSrc(src);
            }
        }

        if (srcFiles.size() == 0)
        {
            final String message = Messages.getString("vfs.tasks/sync.no-source-files.warn");
            logOrDie(message, Project.MSG_WARN);
            return;
        }

        // Perform the sync
        try
        {
            if (destFileUrl != null)
            {
                handleSingleFile();
            }
            else
            {
                handleFiles();
            }
        }
        catch (final BuildException e)
        {
            throw e;
        }
        catch (final Exception e)
        {
            throw new BuildException(e.getMessage(), e);
        }
    }

    protected void logOrDie(final String message, int level)
    {
        if (!isFailonerror())
        {
            log(message, level);
            return;
        }
        throw new BuildException(message);
    }

    /**
     * Copies the source files to the destination.
     */
    private void handleFiles() throws Exception
    {
        // Locate the destination folder, and make sure it exists
        final FileObject destFolder = resolveFile(destDirUrl);
        destFolder.createFolder();

        // Locate the source files, and make sure they exist
        FileName srcDirName = null;
        if (srcDirUrl != null)
        {
            srcDirName = resolveFile(srcDirUrl).getName();
        }
        final ArrayList srcs = new ArrayList();
        for (int i = 0; i < srcFiles.size(); i++)
        {
            // Locate the source file, and make sure it exists
            final SourceInfo src = (SourceInfo) srcFiles.get(i);
            final FileObject srcFile = resolveFile(src.file);
            if (!srcFile.exists())
            {
                final String message =
                    Messages.getString("vfs.tasks/sync.src-file-no-exist.warn", srcFile);

                logOrDie(message, Project.MSG_WARN);
            }
            else
            {
                srcs.add(srcFile);
            }
        }

        // Scan the source files
        final Set destFiles = new HashSet();
        for (int i = 0; i < srcs.size(); i++)
        {
            final FileObject rootFile = (FileObject) srcs.get(i);
            final FileName rootName = rootFile.getName();

            if (rootFile.getType() == FileType.FILE)
            {
                // Build the destination file name
                String relName = null;
                if (srcDirName == null || !srcDirIsBase)
                {
                    relName = rootName.getBaseName();
                }
                else
                {
                    relName = srcDirName.getRelativeName(rootName);
                }
                final FileObject destFile = destFolder.resolveFile(relName, NameScope.DESCENDENT);

                // Do the copy
                handleFile(destFiles, rootFile, destFile);
            }
            else
            {
                // Find matching files
                // If srcDirIsBase is true, select also the sub-directories
                final FileObject[] files = rootFile.findFiles(srcDirIsBase
                    ? Selectors.SELECT_ALL : Selectors.SELECT_FILES);

                for (int j = 0; j < files.length; j++)
                {
                    final FileObject srcFile = files[j];

                    // Build the destination file name
                    String relName = null;
                    if (srcDirName == null || !srcDirIsBase)
                    {
                        relName = rootName.getRelativeName(srcFile.getName());
                    }
                    else
                    {
                        relName = srcDirName.getRelativeName(srcFile.getName());
                    }

                    final FileObject destFile =
                        destFolder.resolveFile(relName, NameScope.DESCENDENT);

                    // Do the copy
                    handleFile(destFiles, srcFile, destFile);
                }
            }
        }

        // Scan the destination files for files with no source file
        if (detectMissingSourceFiles())
        {
            final FileObject[] allDestFiles = destFolder.findFiles(Selectors.SELECT_FILES);
            for (int i = 0; i < allDestFiles.length; i++)
            {
                final FileObject destFile = allDestFiles[i];
                if (!destFiles.contains(destFile))
                {
                    handleMissingSourceFile(destFile);
                }
            }
        }
    }

    /**
     * Handles a single file, checking for collisions where more than one
     * source file maps to the same destination file.
     */
    private void handleFile(final Set destFiles,
                            final FileObject srcFile,
                            final FileObject destFile) throws Exception

    {
        // Check for duplicate source files
        if (destFiles.contains(destFile))
        {
            final String message = Messages.getString("vfs.tasks/sync.duplicate-source-files.warn", destFile);
            logOrDie(message, Project.MSG_WARN);
        }
        else
        {
            destFiles.add(destFile);
        }

        // Handle the file
        handleFile(srcFile, destFile);
    }

    /**
     * Copies a single file.
     */
    private void handleSingleFile() throws Exception
    {
        // Make sure there is exactly one source file, and that it exists
        // and is a file.
        if (srcFiles.size() > 1)
        {
            final String message =
                Messages.getString("vfs.tasks/sync.too-many-source-files.error");
            logOrDie(message, Project.MSG_WARN);
            return;
        }
        final SourceInfo src = (SourceInfo) srcFiles.get(0);
        final FileObject srcFile = resolveFile(src.file);
        if (srcFile.getType() != FileType.FILE)
        {
            final String message =
                Messages.getString("vfs.tasks/sync.source-not-file.error", srcFile);
            logOrDie(message, Project.MSG_WARN);
            return;
        }

        // Locate the destination file
        final FileObject destFile = resolveFile(destFileUrl);

        // Do the copy
        handleFile(srcFile, destFile);
    }

    /**
     * Handles a single source file.
     */
    private void handleFile(final FileObject srcFile,
                            final FileObject destFile)
        throws Exception
    {
        if (!destFile.exists()
            || srcFile.getContent().getLastModifiedTime() > destFile.getContent().getLastModifiedTime())
        {
            // Destination file is out-of-date
            handleOutOfDateFile(srcFile, destFile);
        }
        else
        {
            // Destination file is up-to-date
            handleUpToDateFile(srcFile, destFile);
        }
    }

    /**
     * Handles an out-of-date file (a file where the destination file
     * either doesn't exist, or is older than the source file).
     * This implementation does nothing.
     */
    protected void handleOutOfDateFile(final FileObject srcFile,
                                       final FileObject destFile)
        throws Exception
    {
    }

    /**
     * Handles an up-to-date file (where the destination file exists and is
     * newer than the source file).  This implementation does nothing.
     */
    protected void handleUpToDateFile(final FileObject srcFile,
                                      final FileObject destFile)
        throws Exception
    {
    }

    /**
     * Handles a destination for which there is no corresponding source file.
     * This implementation does nothing.
     */
    protected void handleMissingSourceFile(final FileObject destFile)
        throws Exception
    {
    }

    /**
     * Check if this task cares about destination files with a missing source
     * file.  This implementation returns false.
     */
    protected boolean detectMissingSourceFiles()
    {
        return false;
    }

    /**
     * Information about a source file.
     */
    public static class SourceInfo
    {
        private String file;

        public void setFile(final String file)
        {
            this.file = file;
        }
    }

}
