/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2013 Phillip Schichtel
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
package de.cubeisland.maven.plugins.githead.mojo;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

/**
 * This mojo adds the git head hash as a variable
 *
 * @goal head
 * @phase process-sources
 * @threadSafe
 */
public class HeadMojo extends AbstractMojo
{
    /**
     * @parameter default-value="${project}"
     * @required
     * @readonly
     */
    private MavenProject project;

    /**
     * @parameter expression="${githead.repoLocation}"
     */
    public File repoLocation = new File(".");

    /**
     * @parameter
     */
    public boolean searchParentDirectories = true;

    /**
     * @parameter expression="${githead.defaultBranch}"
     */
    public String defaultBranch = "unknown";

    /**
     * @parameter expression="${githead.defaultCommit}"
     */
    public String defaultCommit = "unknown";

    private final String HEAD_FILE_NAME = "HEAD";
    private final String HEAD_REF_PREFIX = "ref:";
    private final String GIT_FOLDER = ".git";

    public void execute() throws MojoExecutionException, MojoFailureException
    {
        File repo = this.repoLocation.getAbsoluteFile();
        try
        {
            repo = repo.getCanonicalFile();
        }
        catch (IOException ignored)
        {}
        File tmp;
        do
        {
            tmp = new File(repo, GIT_FOLDER);
            if (tmp.exists() && tmp.isDirectory())
            {
                break;
            }
        }
        while (this.searchParentDirectories && (repo = repo.getParentFile()) != null);

        String branch = null;
        String commit = null;

        if (repo != null && repo.exists() && repo.isDirectory())
        {
            String ref = this.readRef(repo);
            if (ref != null)
            {
                branch = refToBranch(ref);
                commit = readHeadCommit(repo, ref);
            }
        }
        else
        {
            getLog().warn("No valid git repository found! Started from: " + this.repoLocation.getAbsolutePath());
        }

        if (branch == null)
        {
            branch = this.defaultBranch;
        }
        if (commit == null)
        {
            commit = this.defaultCommit;
        }

        Properties properties = this.project.getProperties();
        properties.put("githead.branch", branch);
        properties.put("githead.commit", commit);

        getLog().info("Found: " + branch + "/" + commit);
    }

    private static String refToBranch(String ref)
    {
        String[] parts = ref.split("/");
        String branch = parts[parts.length - 1].trim();
        if (branch.equals(""))
        {
            return null;
        }
        return branch;
    }

    private String readHeadCommit(File repo, String ref)
    {
        File refFile = new File(repo, GIT_FOLDER + File.separator + ref);

        BufferedReader reader = null;
        String commitHash = null;
        try
        {
            reader = new BufferedReader(new FileReader(refFile));

            while ((commitHash = reader.readLine()) != null)
            {
                commitHash = commitHash.trim();
                if (!commitHash.isEmpty())
                {
                    break;
                }
            }
        }
        catch (FileNotFoundException e)
        {
            getLog().warn("The file " + refFile.getPath() + " could not be found!", e);
        }
        catch (IOException e)
        {
            getLog().warn("Failed to read the ref file", e);
        }
        finally
        {
            if (reader != null)
            {
                try
                {
                    reader.close();
                }
                catch (IOException ignored)
                {}
            }
        }
        return commitHash;
    }

    private String readRef(File repo)
    {
        File headFile = new File(repo, GIT_FOLDER + File.separator + HEAD_FILE_NAME);

        BufferedReader reader = null;
        String refPath = null;
        try
        {
            reader = new BufferedReader(new FileReader(headFile));

            String line;
            while ((line = reader.readLine()) != null)
            {
                line = line.trim();
                if (line.toLowerCase().startsWith(HEAD_REF_PREFIX))
                {
                    refPath = line.substring(HEAD_REF_PREFIX.length()).trim();
                    break;
                }
            }

        }
        catch (FileNotFoundException e)
        {
            getLog().warn("The file " + headFile.getPath() + " could not be found!", e);
        }
        catch (IOException e)
        {
            getLog().warn("Failed to read the " + HEAD_FILE_NAME + " file", e);
        }
        finally
        {
            if (reader != null)
            {
                try
                {
                    reader.close();
                }
                catch (IOException ignored)
                {}
            }
        }
        return refPath;
    }
}

@@ -1880,38 +1880,34 @@
  @parameter 
-expression=%22$%7B
+property=%22
 githead.repo
@@ -1914,16 +1914,50 @@
 Location
+%22 default-value=%22$%7Bproject.basedir
 %7D%22%0A     
@@ -1991,24 +1991,8 @@
 tion
- = new File(%22.%22)
 ;%0A%0A 
@@ -2015,16 +2015,59 @@
 arameter
+ property=%22githead.searchParentDirectories%22
 %0A     */
@@ -2141,38 +2141,34 @@
  @parameter 
-expression=%22$%7B
+property=%22
 githead.defa
@@ -2176,17 +2176,16 @@
 ltBranch
-%7D
 %22%0A     *
@@ -2262,22 +2262,18 @@
 ter 
-expression=%22$%7B
+property=%22
 gith
@@ -2289,17 +2289,16 @@
 ltCommit
-%7D
 %22%0A     *
@@ -2349,32 +2349,39 @@
 %22;%0A%0A    private 
+static 
 final String HEA
@@ -2406,32 +2406,39 @@
 D%22;%0A    private 
+static 
 final String HEA
@@ -2472,16 +2472,23 @@
 private 
+static 
 final St

use the basedir instead of the working directory by default