/*
 * 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.maven.scm.provider.git.gitexe.command.status;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.maven.scm.ScmFile;
import org.apache.maven.scm.ScmFileSet;
import org.apache.maven.scm.ScmFileStatus;
import org.apache.maven.scm.util.AbstractConsumer;

/**
 * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
 */
public class GitStatusConsumer extends AbstractConsumer {

    /**
     * The pattern used to match added file lines
     */
    private static final Pattern ADDED_PATTERN = Pattern.compile("^A[ M]* (.*)$");

    /**
     * The pattern used to match modified file lines
     */
    private static final Pattern MODIFIED_PATTERN = Pattern.compile("^ *M[ M]* (.*)$");

    /**
     * The pattern used to match deleted file lines
     */
    private static final Pattern DELETED_PATTERN = Pattern.compile("^ *D * (.*)$");

    /**
     * The pattern used to match renamed file lines
     */
    private static final Pattern RENAMED_PATTERN = Pattern.compile("^R  (.*) -> (.*)$");

    private final File workingDirectory;

    private ScmFileSet scmFileSet;

    /**
     * Entries are relative to working directory, not to the repositoryroot
     */
    private final List<ScmFile> changedFiles = new ArrayList<>();

    private URI relativeRepositoryPath;

    // ----------------------------------------------------------------------
    //
    // ----------------------------------------------------------------------

    /**
     * Consumer when workingDirectory and repositoryRootDirectory are the same
     *
     * @param workingDirectory the working directory
     */
    public GitStatusConsumer(File workingDirectory) {
        this.workingDirectory = workingDirectory;
    }

    /**
     * Assuming that you have to discover the repositoryRoot, this is how you can get the
     * <code>relativeRepositoryPath</code>
     * <pre>
     * URI.create( repositoryRoot ).relativize( fileSet.getBasedir().toURI() )
     * </pre>
     *
     * @param workingDirectory the working directory
     * @param relativeRepositoryPath the working directory relative to the repository root
     * @since 1.9
     * @see GitStatusCommand#createRevparseShowPrefix(ScmFileSet)
     */
    public GitStatusConsumer(File workingDirectory, URI relativeRepositoryPath) {
        this(workingDirectory);
        this.relativeRepositoryPath = relativeRepositoryPath;
    }

    /**
     * Assuming that you have to discover the repositoryRoot, this is how you can get the
     * <code>relativeRepositoryPath</code>
     * <pre>
     * URI.create( repositoryRoot ).relativize( fileSet.getBasedir().toURI() )
     * </pre>
     *
     * @param workingDirectory the working directory
     * @param scmFileSet fileset with includes and excludes
     * @since 1.11.0
     * @see GitStatusCommand#createRevparseShowPrefix(ScmFileSet)
     */
    public GitStatusConsumer(File workingDirectory, ScmFileSet scmFileSet) {
        this(workingDirectory);
        this.scmFileSet = scmFileSet;
    }

    /**
     * Assuming that you have to discover the repositoryRoot, this is how you can get the
     * <code>relativeRepositoryPath</code>
     * <pre>
     * URI.create( repositoryRoot ).relativize( fileSet.getBasedir().toURI() )
     * </pre>
     *
     * @param workingDirectory the working directory
     * @param relativeRepositoryPath the working directory relative to the repository root
     * @param scmFileSet fileset with includes and excludes
     * @since 1.11.0
     * @see GitStatusCommand#createRevparseShowPrefix(ScmFileSet)
     */
    public GitStatusConsumer(File workingDirectory, URI relativeRepositoryPath, ScmFileSet scmFileSet) {
        this(workingDirectory, scmFileSet);
        this.relativeRepositoryPath = relativeRepositoryPath;
    }

    // ----------------------------------------------------------------------
    // StreamConsumer Implementation
    // ----------------------------------------------------------------------

    /**
     * {@inheritDoc}
     */
    public void consumeLine(String line) {
        if (logger.isDebugEnabled()) {
            logger.debug(line);
        }
        if (line == null || line.isEmpty()) {
            return;
        }

        ScmFileStatus status = null;

        List<String> files = new ArrayList<String>();

        Matcher matcher;
        if ((matcher = ADDED_PATTERN.matcher(line)).find()) {
            status = ScmFileStatus.ADDED;
            files.add(resolvePath(matcher.group(1), relativeRepositoryPath));
        } else if ((matcher = MODIFIED_PATTERN.matcher(line)).find()) {
            status = ScmFileStatus.MODIFIED;
            files.add(resolvePath(matcher.group(1), relativeRepositoryPath));
        } else if ((matcher = DELETED_PATTERN.matcher(line)).find()) {
            status = ScmFileStatus.DELETED;
            files.add(resolvePath(matcher.group(1), relativeRepositoryPath));
        } else if ((matcher = RENAMED_PATTERN.matcher(line)).find()) {
            status = ScmFileStatus.RENAMED;
            files.add(resolvePath(matcher.group(1), relativeRepositoryPath));
            files.add(resolvePath(matcher.group(2), relativeRepositoryPath));
            logger.debug("RENAMED status for line '" + line + "' files added '" + matcher.group(1) + "' '"
                    + matcher.group(2));
        } else {
            logger.warn("Ignoring unrecognized line: " + line);
            return;
        }

        // If the file isn't a file; don't add it.
        if (!files.isEmpty()) {
            if (workingDirectory != null) {
                if (status == ScmFileStatus.RENAMED) {
                    String oldFilePath = files.get(0);
                    String newFilePath = files.get(1);
                    if (isFile(oldFilePath)) {
                        logger.debug("file '" + oldFilePath + "' is a file");
                        return;
                    } else {
                        logger.debug("file '" + oldFilePath + "' not a file");
                    }
                    if (!isFile(newFilePath)) {
                        logger.debug("file '" + newFilePath + "' not a file");
                        return;
                    } else {
                        logger.debug("file '" + newFilePath + "' is a file");
                    }
                } else if (status == ScmFileStatus.DELETED) {
                    if (isFile(files.get(0))) {
                        return;
                    }
                } else {
                    if (!isFile(files.get(0))) {
                        return;
                    }
                }
            }

            for (String file : files) {
                if (this.scmFileSet != null && !isFileNameInFileList(this.scmFileSet.getFileList(), file)) {
                    // skip adding this file
                } else {
                    changedFiles.add(new ScmFile(file, status));
                }
            }
        }
    }

    private boolean isFileNameInFileList(List<File> fileList, String fileName) {
        if (relativeRepositoryPath == null) {
            return fileList.contains(new File(fileName));
        } else {
            for (File f : fileList) {
                File file = new File(relativeRepositoryPath.getPath(), fileName);
                if (file.getPath().endsWith(f.getName())) {
                    return true;
                }
            }
            return fileList.isEmpty();
        }
    }

    private boolean isFile(String file) {
        File targetFile = new File(workingDirectory, file);
        return targetFile.isFile();
    }

    public static String resolvePath(String fileEntry, URI path) {
        /* Quotes may be included (from the git status line) when an fileEntry includes spaces */
        String cleanedEntry = stripQuotes(fileEntry);
        if (path != null) {
            return resolveURI(cleanedEntry, path).getPath();
        } else {
            return cleanedEntry;
        }
    }

    /**
     *
     * @param fileEntry the fileEntry, must not be {@code null}
     * @param path the path, must not be {@code null}
     * @return TODO
     */
    public static URI resolveURI(String fileEntry, URI path) {
        // When using URI.create, spaces need to be escaped but not the slashes, so we can't use
        // URLEncoder.encode( String, String )
        // new File( String ).toURI() results in an absolute URI while path is relative, so that can't be used either.
        return path.relativize(uriFromPath(stripQuotes(fileEntry)));
    }

    /**
     * Create an URI whose getPath() returns the given path and getScheme() returns null. The path may contain spaces,
     * colons, and other special characters.
     *
     * @param path the path.
     * @return the new URI
     */
    public static URI uriFromPath(String path) {
        try {
            if (path != null && path.indexOf(':') != -1) {
                // prefixing the path so the part preceding the colon does not become the scheme
                String tmp = new URI(null, null, "/x" + path, null).toString().substring(2);
                // the colon is not escaped by default
                return new URI(tmp.replace(":", "%3A"));
            } else {
                return new URI(null, null, path, null);
            }
        } catch (URISyntaxException x) {
            throw new IllegalArgumentException(x.getMessage(), x);
        }
    }

    public List<ScmFile> getChangedFiles() {
        return changedFiles;
    }

    /**
     * @param str the (potentially quoted) string, must not be {@code null}
     * @return the string with a pair of double quotes removed (if they existed)
     */
    private static String stripQuotes(String str) {
        int strLen = str.length();
        return (strLen > 0 && str.startsWith("\"") && str.endsWith("\""))
                ? unescape(str.substring(1, strLen - 1))
                : str;
    }

    /**
     * Dequote a quoted string generated by git status --porcelain.
     * The leading and trailing quotes have already been removed.
     * @param fileEntry
     * @return TODO
     */
    private static String unescape(String fileEntry) {
        // If there are no escaped characters, just return the input argument
        int pos = fileEntry.indexOf('\\');
        if (pos == -1) {
            return fileEntry;
        }

        // We have escaped characters
        byte[] inba = fileEntry.getBytes();
        int inSub = 0; // Input subscript into fileEntry
        byte[] outba = new byte[fileEntry.length()];
        int outSub = 0; // Output subscript into outba

        while (true) {
            System.arraycopy(inba, inSub, outba, outSub, pos - inSub);
            outSub += pos - inSub;
            inSub = pos + 1;
            switch ((char) inba[inSub++]) {
                case '"':
                    outba[outSub++] = '"';
                    break;

                case 'a':
                    outba[outSub++] = 7; // Bell
                    break;

                case 'b':
                    outba[outSub++] = '\b';
                    break;

                case 't':
                    outba[outSub++] = '\t';
                    break;

                case 'n':
                    outba[outSub++] = '\n';
                    break;

                case 'v':
                    outba[outSub++] = 11; // Vertical tab
                    break;

                case 'f':
                    outba[outSub++] = '\f';
                    break;

                case 'r':
                    outba[outSub++] = '\f';
                    break;

                case '\\':
                    outba[outSub++] = '\\';
                    break;

                case '0':
                case '1':
                case '2':
                case '3':
                    // This assumes that the octal escape here is valid.
                    byte b = (byte) ((inba[inSub - 1] - '0') << 6);
                    b |= (byte) ((inba[inSub++] - '0') << 3);
                    b |= (byte) (inba[inSub++] - '0');
                    outba[outSub++] = b;
                    break;

                default:
                    // This is an invalid escape in a string.  Just copy it.
                    outba[outSub++] = '\\';
                    inSub--;
                    break;
            }
            pos = fileEntry.indexOf('\\', inSub);
            if (pos == -1) // No more backslashes; we're done
            {
                System.arraycopy(inba, inSub, outba, outSub, inba.length - inSub);
                outSub += inba.length - inSub;
                break;
            }
        }
        try {
            // explicit say UTF-8, otherwise it'll fail at least on Windows cmdline
            return new String(outba, 0, outSub, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }
}
