// 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 com.google.gerrit.acceptance.{GitUtil, UseLocalDisk}
import com.google.gerrit.entities.Project
import com.googlesource.gerrit.plugins.analytics.CommitInfo
import com.googlesource.gerrit.plugins.analytics.common.{CommitsStatistics, Statistics}
import org.scalatest.Inside
import org.scalatest.flatspec.AnyFlatSpecLike
import org.scalatest.matchers.should.Matchers

@UseLocalDisk
class CommitStatisticsSpec extends AnyFlatSpecLike with GerritTestDaemon with TestCommitStatisticsNoCache with Matchers with Inside {
  class TestEnvironment {
    val repo = fileRepository
    val stats = new Statistics(fileRepositoryName, commitsStatisticsNoCache)
  }

  "CommitStatistics" should "stats a single file added" in new TestEnvironment {
    val change = testFileRepository.commitFile("file1.txt", "line1\nline2")

    inside(stats.forCommits(change)) { case List(s: CommitsStatistics) =>
      s.numFiles should be(1)
      s.addedLines should be(2)
      s.deletedLines should be(0)
    }
  }

  it should "sum to another compatible CommitStatistics generating an aggregated stat" in {
    val commit1 = CommitInfo("sha_1", 1000L, false, botLike = false, Set("file1"))
    val commit2 = CommitInfo("sha_2", 2000L, false, botLike = false, Set("file1"))
    val commit3 = CommitInfo("sha_3", 3000L, false, botLike = false, Set("file2"))
    val commit4 = CommitInfo("sha_4", 1000L, false, botLike = false, Set("file1"))

    val stat1 = CommitsStatistics(3, 4, false, false, List(commit1, commit2))
    val stat2 = CommitsStatistics(5, 7, false, false, List(commit3, commit4))

    (stat1 + stat2) shouldBe CommitsStatistics(8, 11, false, false, List(commit1, commit2, commit3, commit4))
  }

  it should "fail if trying to be added to a CommitStatistics object for a different isMerge value" in {
    an [IllegalArgumentException] should be thrownBy  (CommitsStatistics.EmptyMerge + CommitsStatistics.EmptyNonMerge)
  }

  it should "stats multiple files added" in new TestEnvironment {
    val initial = testFileRepository.commitFile("file1.txt", "line1\nline2\n")
    val second = testFileRepository.commitFiles(
      List(
        "file1.txt" -> "line1\n",
        "file2.txt" -> "line1\nline2\n"
      ), message = "second commit")

    inside(stats.forCommits(second)) { case List(s: CommitsStatistics) =>
      s.numFiles should be(2)
      s.addedLines should be(2)
      s.deletedLines should be(1)
    }
  }

  it should "stats lines eliminated" in new TestEnvironment {
    val initial = testFileRepository.commitFile( "file1.txt", "line1\nline2\nline3")
    val second = testFileRepository.commitFile( "file1.txt", "line1\n")
    inside(stats.forCommits(second)) { case List(s: CommitsStatistics) =>
      s.numFiles should be(1)
      s.addedLines should be(0)
      s.deletedLines should be(2)
    }
  }

  it should "stats a Seq[RevCommit]" in new TestEnvironment {
    val initial = testFileRepository.commitFiles(
      List(
        "file1.txt" -> "line1\n",
        "file3.txt" -> "line1\nline2\n"),
      message = "first commit")

    val second = testFileRepository.commitFiles(
      List(
        "file1.txt" -> "line1a\n",
        "file2.txt" -> "line1\nline2\n"),
      message = "second commit")

    inside(stats.forCommits(initial, second)) { case List(nonMergeStats: CommitsStatistics) =>
      nonMergeStats.numFiles should be(4)
      nonMergeStats.numDistinctFiles should be(3)
      nonMergeStats.addedLines should be(6)
      nonMergeStats.deletedLines should be(1)
    }
  }

  it should "return zero value stats if the commit does not include any file" in new TestEnvironment {
    val emptyCommit = testFileRepository.commitFiles(List.empty, message = "Empty commit")
    inside(stats.forCommits(emptyCommit)) { case List(stats) =>
      stats.numFiles should be(0)
      stats.addedLines should be(0)
      stats.deletedLines should be(0)
    }
  }

  it should "split merge commits and non-merge commits" in {
    val newProjectKey: Project.NameKey = daemonTest.newProject(testSpecificRepositoryName, true)
    val repository = daemonTest.getRepository(newProjectKey)
    val clonedRepo = GitUtil.newTestRepository(repository).gitClone
    val stats = new Statistics(newProjectKey, commitsStatisticsNoCache)

    val firstNonMerge = clonedRepo.commitFile("file1.txt", "line1\nline2\n")
    val merge = clonedRepo.mergeCommitFile("file1.txt", "line1\nline2\nline3")
    val nonMerge = clonedRepo.commitFiles(
      List(
        "file1.txt" -> "line1\n",
        "file2.txt" -> "line1\nline2\n"),
      message = "second commit")
    clonedRepo.push

    inside(stats.forCommits(firstNonMerge, merge.getNewHead, nonMerge)) {
      case List(nonMergeStats, mergeStats) =>
        mergeStats.numFiles should be(1)
        mergeStats.addedLines should be(1)
        mergeStats.deletedLines should be(0)

        nonMergeStats.numFiles should be(3)
        nonMergeStats.addedLines should be(4)
        nonMergeStats.deletedLines should be(2)

      case wrongContent => fail(s"Expected two results instead got $wrongContent")
    }
  }
}
