//
// Copyright (c) 2011 Kevin Sawicki <kevinsawicki@gmail.com>
//
// 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.
//
// Copyright (C) 2017 The Android Open Source Project
//
// Licensed 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 com.googlesource.gerrit.plugins.analytics.test

import java.io.{File, PrintWriter}
import java.nio.file.Files
import java.text.MessageFormat
import java.util.Date

import com.googlesource.gerrit.plugins.analytics.common.ManagedResource.use
import org.eclipse.jgit.api.MergeCommand.FastForwardMode
import org.eclipse.jgit.api.{Git, MergeResult}
import org.eclipse.jgit.api.errors.GitAPIException
import org.eclipse.jgit.lib.{Constants, PersonIdent, Ref}
import org.eclipse.jgit.merge.MergeStrategy
import org.eclipse.jgit.notes.Note
import org.eclipse.jgit.revwalk.RevCommit
import org.gitective.core.CommitUtils
import org.scalatest.{BeforeAndAfterEach, Suite}


/**
  * Base test case with utilities for common Git operations performed during
  * testing
  */
trait GitTestCase extends BeforeAndAfterEach {
  self: Suite =>
  /**
    * Test repository .git directory
    */
  protected var testRepo: File = null

  /**
    * Author used for commits
    */
  protected val author = new PersonIdent("Test Author", "author@test.com")

  def newPersonIdent(name: String = "Test Person", email: String = "person@test.com", ts: Date = new Date()) =
    new PersonIdent(new PersonIdent(name, email), ts)

  /**
    * Committer used for commits
    */
  protected val committer = new PersonIdent("Test Committer", "committer@test.com")

  /**
    * Set up method that initializes git repository
    *
    *
    */

  override def beforeEach = {
    testRepo = initRepo
  }

  /**
    * Initialize a new repo in a new directory
    *
    * @return created .git folder
    * @throws GitAPIException
    */
  protected def initRepo: File = {
    val dir = Files.createTempDirectory(threadSpecificDirectoryPrefix).toFile
    Git.init.setDirectory(dir).setBare(false).call
    val repo = new File(dir, Constants.DOT_GIT)
    assert(repo.exists)
    repo.deleteOnExit()
    repo
  }

  private def threadSpecificDirectoryPrefix =
    "git-test-case-" + Thread.currentThread().getName.replaceAll("~[0-9a-zA-Z]", "_") + System.nanoTime

  /**
    * Create branch with name and checkout
    *
    * @param name
    * @return branch ref
    *
    */
  protected def branch(name: String): Ref = branch(testRepo, name)

  /**
    * Delete branch with name
    *
    * @param name
    * @return branch ref
    *
    */
  protected def deleteBranch(name: String): String = deleteBranch(testRepo, name)

  /**
    * Create branch with name and checkout
    *
    * @param repo
    * @param name
    * @return branch ref
    *
    */
  protected def branch(repo: File, name: String): Ref = {
    use(Git.open(repo)) { git =>
      git.branchCreate.setName(name).call
      checkout(repo, name)
    }
  }

  /**
    * Delete branch with name
    *
    * @param repo
    * @param name
    * @return branch ref
    *
    */
  protected def deleteBranch(repo: File, name: String): String = {
    use(Git.open(repo)) { git =>
      git.branchDelete().setBranchNames(name).setForce(true).call.get(0)
    }
  }

  /**
    * Checkout branch
    *
    * @param name
    * @return branch ref
    *
    */
  protected def checkout(name: String): Ref = checkout(testRepo, name)

  /**
    * Checkout branch
    *
    * @param repo
    * @param name
    * @return branch ref
    *
    */
  @throws[Exception]
  protected def checkout(repo: File, name: String): Ref = {
    use(Git.open(repo)) { git =>
      git.checkout.setName(name).call
    }
  } ensuring(_ != null, "Unable to checkout result")

  /**
    * Create tag with name
    *
    * @param name
    * @return tag ref
    *
    */
  protected def tag(name: String): Ref = tag(testRepo, name)

  /**
    * Create tag with name
    *
    * @param repo
    * @param name
    * @return tag ref
    *
    */
  protected def tag(repo: File, name: String): Ref = {
    use(Git.open(repo)) { git =>
      git.tag.setName(name).setMessage(name).call
      git.getRepository.getTags.get(name)
    }
  } ensuring(_ != null, s"Unable to tag file $name")

  /**
    * Add file to test repository
    *
    * @param path
    * @param content
    * @return commit
    *
    */
  protected def add(path: String, content: String, author: PersonIdent = author, committer: PersonIdent = committer): RevCommit = add(testRepo, path, content, author, committer)

  /**
    * Add file to test repository
    *
    * @param repo
    * @param path
    * @param content
    * @return commit
    *
    */
  protected def add(repo: File, path: String, content: String, author: PersonIdent, committer: PersonIdent): RevCommit = {
    val message = MessageFormat.format("Committing {0} at {1}", path, new Date)
    add(repo, path, content, message, author, committer)
  }


  /**
    * Add file to test repository
    *
    * @param repo
    * @param path
    * @param content
    * @param message
    * @return commit
    *
    */
  protected def add(repo: File, path: String, content: String, message: String, author: PersonIdent, committer: PersonIdent): RevCommit = {
    val file = new File(repo.getParentFile, path)
    if (!file.getParentFile.exists) assert(file.getParentFile.mkdirs)
    if (!file.exists) assert(file.createNewFile)

    val writer = new PrintWriter(file)
    try
      writer.print(Option(content).fold("")(identity))
    finally writer.close()

    use(Git.open(repo)) { git =>
      git.add.addFilepattern(path).call
      git.commit.setOnly(path).setMessage(message).setAuthor(author).setCommitter(committer).call
    }
  }  ensuring (_ != null, s"Unable to commit addition of path $path")

  /**
    * Move file in test repository
    *
    * @param from
    * @param to
    * @return commit
    *
    */
  protected def mv(from: String, to: String): RevCommit = mv(testRepo, from, to, MessageFormat.format("Moving {0} to {1} at {2}", from, to, new Date))

  /**
    * Move file in test repository
    *
    * @param from
    * @param to
    * @param message
    * @return commit
    *
    */
  protected def mv(from: String, to: String, message: String): RevCommit = mv(testRepo, from, to, message)

  /**
    * Move file in test repository
    *
    * @param repo
    * @param from
    * @param to
    * @param message
    * @return commit
    *
    */
  protected def mv(repo: File, from: String, to: String, message: String): RevCommit = {
    val file = new File(repo.getParentFile, from)
    file.renameTo(new File(repo.getParentFile, to))

    use(Git.open(testRepo)) { git =>
      git.rm.addFilepattern(from)
      git.add.addFilepattern(to).call
      git.commit.setAll(true).setMessage(message).setAuthor(author).setCommitter(committer).call
    }
  } ensuring (_ != null, "Unable to commit MV operation")

  /**
    * Add files to test repository
    *
    * @param contents iterable of file names and associated content
    * @return commit
    *
    */
  protected def add(contents: Iterable[(String, String)]): RevCommit = add(testRepo, contents, "Committing multiple files")

  /**
    * Add files to test repository
    *
    * @param repo
    * @param contents iterable of file names and associated content
    * @param message
    * @return commit
    *
    */
  protected def add(repo: File, contents: Iterable[(String, String)], message: String): RevCommit = {
    use(Git.open(testRepo)) { git =>
      var i = 0
      contents.foreach { case (path, content) =>
        val file = new File(repo.getParentFile, path)
        if (!file.getParentFile.exists) require(file.getParentFile.mkdirs, s"Cannot create parent dir '${file.getParent}'")
        if (!file.exists) require(file.createNewFile, s"Cannot create file '$file'")
        val writer = new PrintWriter(file)
        try
          writer.print(content)
        finally writer.close()
        git.add.addFilepattern(path).call
      }

      git.commit.setMessage(message).setAuthor(author).setCommitter(committer).call
    }
  } ensuring (_ != null, "Unable to commit content addition")

  /**
    * Merge given branch into current branch
    *
    * @param branch
    * @return result
    *
    */
  protected def mergeBranch(branch: String, withCommit: Boolean): MergeResult = {
    use(Git.open(testRepo)) { git =>
      git.merge.setStrategy(MergeStrategy.RESOLVE).include(CommitUtils.getRef(git.getRepository, branch)).setCommit(withCommit).setFastForward(FastForwardMode.NO_FF).setMessage(s"merging branch $branch").call
    }
  }

    /**
    * Merge ref into current branch
    *
    * @param ref
    * @return result
    *
    */
  protected def merge(ref: String): MergeResult = {
    use(Git.open(testRepo)) { git =>
      git.merge.setStrategy(MergeStrategy.RESOLVE).include(CommitUtils.getCommit(git.getRepository, ref)).call
    }
  }

  /**
    * Add note to latest commit with given content
    *
    * @param content
    * @return note
    *
    */
  protected def note(content: String): Note = note(content, "commits")

  /**
    * Add note to latest commit with given content
    *
    * @param content
    * @param ref
    * @return note
    *
    */
  protected def note(content: String, ref: String): Note = {
    use(Git.open(testRepo)) { git =>
      git.notesAdd.setMessage(content).setNotesRef(Constants.R_NOTES + ref).setObjectId(CommitUtils.getHead(git.getRepository)).call
    }
  } ensuring (_ != null, "Unable to add note")

  /**
    * Delete and commit file at path
    *
    * @param path
    * @return commit
    *
    */
  protected def delete(path: String): RevCommit = {
    val message = MessageFormat.format("Committing {0} at {1}", path, new Date)
    use(Git.open(testRepo)) { git =>
      git.rm.addFilepattern(path).call
      git.commit.setOnly(path).setMessage(message).setAuthor(author).setCommitter(committer).call
    }
  } ensuring (_ != null, "Unable to commit delete operation")
}