//
// 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.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 tmpDir = System.getProperty("java.io.tmpdir")
    assert(tmpDir != null, "java.io.tmpdir was null")
    val dir = new File(tmpDir, "git-test-case-" + System.nanoTime)
    assert(dir.mkdir)
    Git.init.setDirectory(dir).setBare(false).call
    val repo = new File(dir, Constants.DOT_GIT)
    assert(repo.exists)
    repo.deleteOnExit()
    repo
  }

  /**
    * 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).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")
}