// Copyright (C) 2019 GerritForge Ltd
//
// 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.google.gerrit.server.notedb

import java.util.function.Supplier

import com.google.gerrit.entities.Change.Id
import com.google.gerrit.entities.Project
import com.google.gerrit.server.notedb.ChangeNotesCommit.ChangeNotesRevWalk
import com.google.inject.Inject
import com.google.inject.assistedinject.Assisted
import com.googlesource.gerrit.plugins.analytics.common.ManagedResource.use
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.lib.{AnyObjectId, Ref, Repository}
import org.eclipse.jgit.revwalk.RevCommit
import org.slf4j.LoggerFactory

import scala.collection.JavaConverters._
import scala.util.Try

trait HashTagsExtractorFactory {
  def create(projectKey: Project.NameKey, repo: Repository): HashTagsExtractor
}

trait HashTagsExtractor {
  def hashTagsOfCommit(revCommit: RevCommit): Set[String]
}

final case class HashTagsExtractorImpl @Inject() (
    @Assisted projectKey: Project.NameKey,
    @Assisted repo: Repository,
    changeNotesCache: ChangeNotesCache) extends HashTagsExtractor {

  private val log = LoggerFactory.getLogger(classOf[HashTagsExtractorImpl])

  lazy val objectsToRefs: collection.Map[AnyObjectId, Set[Ref]] = {
    use(new Git(repo)) {
      _.getRepository.getAllRefsByPeeledObjectId.asScala.mapValues(_.asScala.toSet)
    }
  }

  lazy val refsToObjects: Map[String, AnyObjectId] =
    objectsToRefs.foldLeft(Map[String, AnyObjectId]()) { case (acc, (objectId, refs)) =>
      acc ++ refs.toSeq.flatMap { ref =>
        Map(ref.getName -> objectId)
      }.toMap
    }

  def hashTagsOfCommit(revCommit: RevCommit): Set[String] = {
    val maybeRefs = objectsToRefs.get(revCommit.toObjectId)
    maybeRefs.map { refs =>
      log.debug(s"Extracting meta refs from ${refs.map(_.getName).mkString(",")}")
      // We can take the first one since we know there is a one to one mapping between change refs and commit objects in Gerrit
      refs.collectFirst {
        case c if c.getName.startsWith("refs/changes/") => {
          val changeName = c.getName
          val metaRefString = changeName.take(changeName.lastIndexOf("/")).concat("/meta")
          refsToObjects.get(metaRefString).map { metaRefObjectId =>
            val revWalkSupplier = new Supplier[ChangeNotesRevWalk] {
              override def get(): ChangeNotesRevWalk = ChangeNotesCommit.newRevWalk(repo)
            }
            Try {
              changeNotesCache
                .get(projectKey, Id.fromRef(metaRefString), metaRefObjectId.toObjectId, revWalkSupplier)
                .state()
                .hashtags()
                .asScala
                .toSet
            }.recover {
              case e: Exception =>
                fallBack(Some(s"Could not get changeNote of '${metaRefString}' for project ${projectKey.get()}"), Some(e))
            }.get
          }.getOrElse(fallBack(Some(s"Could not find metaRef object '${metaRefString}'")))
        }
      }.getOrElse(fallBack())
    }.getOrElse(fallBack())
  }

  private def fallBack(maybeDescription: Option[String] = None, maybeException: Option[Throwable] = None): Set[String] = {
    maybeDescription.foreach {
      log.error(_, maybeException.orNull)
    }
    Set.empty[String]
  }
}

