/*
 * Copyright (C) 2015 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.
 */
@file:JvmName("RecipeMergeUtils")

package com.android.tools.idea.templates

import com.android.SdkConstants.ATTR_ID
import com.android.SdkConstants.ATTR_NAME
import com.android.SdkConstants.FN_ANDROID_MANIFEST_XML
import com.android.SdkConstants.XMLNS_PREFIX
import com.android.manifmerger.ManifestMerger2
import com.android.manifmerger.MergingReport
import com.android.manifmerger.XmlDocument
import com.android.resources.ResourceFolderType
import com.android.tools.idea.templates.recipe.RenderingContext
import com.android.utils.StdLogger
import com.android.utils.XmlUtils
import com.google.common.base.Charsets
import com.google.common.collect.Lists.newArrayList
import com.intellij.lang.xml.XMLLanguage
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.PsiFileFactory
import com.intellij.psi.codeStyle.CodeStyleManager
import com.intellij.psi.xml.XmlComment
import com.intellij.psi.xml.XmlFile
import com.intellij.psi.xml.XmlTag
import com.intellij.psi.xml.XmlTagChild
import com.intellij.psi.xml.XmlText
import java.io.ByteArrayInputStream
import java.io.File
import java.io.FileNotFoundException
import java.io.InputStream

/**
 * Utility methods to support the recipe.xml merge instruction.
 */

private val LOG: Logger get() = logger(::LOG)

private const val MERGE_ATTR_STRATEGY = "templateMergeStrategy"
private const val MERGE_ATTR_STRATEGY_REPLACE = "replace"
private const val MERGE_ATTR_STRATEGY_PRESERVE = "preserve"

/**
 * Merges sourceXml into targetXml/targetFile (targetXml is the contents of targetFile).
 * @return the resulting xml if it still needs to be written to targetFile or null if the file has already been/doesn't need to be updated.
 */
fun mergeXml(context: RenderingContext, sourceXml: String, targetXml: String, targetFile: File): String {
  val fileName = targetFile.name
  var errors: String? = null

  fun mergeManifest(): String? {
    XmlUtils.parseDocumentSilently(targetXml, true) ?: error("$targetXml failed to parse")
    XmlUtils.parseDocumentSilently(sourceXml, true) ?: error("$sourceXml failed to parse")
    val report = mergeManifest(context.moduleRoot!!, targetFile, targetXml, sourceXml) ?: return null
    if (report.result.isSuccess) {
      return report.getMergedDocument(MergingReport.MergedManifestKind.MERGED)
    }
    // report.reportString isn't useful, it just says to look at the logs
    // Also, some of the warnings are misleading -- e.g. "missing package declaration";
    // that's deliberate. Users only have to deal with errors to get the manifest merge to succeed.
    errors = report.loggingRecords.asSequence()
      .filter { it.severity == MergingReport.Record.Severity.ERROR }
      .joinToString("") { "* ${it.message}\n\n" }
      .replace("AndroidManifest.xml", "current AndroidManifest.xml") // Error messages may refer to our internal temp name for the target manifest file
      .replace("nevercreated.xml", "template AndroidManifest.xml")
      .trim()
    return null
  }

  fun mergePlainXml(): String {
    val parentFolderName = targetFile.parentFile.name
    val folderType = ResourceFolderType.getFolderType(parentFolderName)
    // mergeResourceFile handles the file updates itself
    return mergeResourceFile(context.project, context.warnings, targetXml, sourceXml, fileName, folderType)
  }

  return (if (fileName == FN_ANDROID_MANIFEST_XML) mergeManifest() else mergePlainXml())
         ?: // Just insert into file along with comment, using the "standard" conflict syntax that many tools and editors recognize.
         wrapWithMergeConflict(targetXml, sourceXml).also {
           context.warnings.add(
             "Merge conflict for: ${targetFile.name}\nThis file must be fixed by hand. Errors encountered during the merge:\n\n$errors")
         }
}

/**
 * Merges the given resource file contents into the given resource file
 */
fun mergeResourceFile(project: Project,
                      warningsToAdd: MutableCollection<String>,
                      targetXml: String,
                      sourceXml: String,
                      fileName: String,
                      folderType: ResourceFolderType?): String {
  val targetPsiFile = PsiFileFactory.getInstance(project)
    .createFileFromText("targetFile", XMLLanguage.INSTANCE, StringUtil.convertLineSeparators(targetXml), false, true) as XmlFile
  val sourcePsiFile = PsiFileFactory.getInstance(project)
    .createFileFromText("sourceFile", XMLLanguage.INSTANCE, StringUtil.convertLineSeparators(sourceXml), false, true) as XmlFile
  val root = targetPsiFile.document!!.rootTag ?: error("Cannot find XML root in target: $targetXml")

  val attributes = sourcePsiFile.rootTag!!.attributes
  attributes.filter {it.namespacePrefix == XMLNS_PREFIX}.forEach { root.setAttribute(it.name, it.value) }

  if (folderType != ResourceFolderType.VALUES) {
    // In other file types, such as layouts, just append all the new content at the end.
    sourcePsiFile.rootTag!!.children.filterIsInstance<XmlTag>().forEach {
      root.addSubTag(it, false)
    }
    return targetPsiFile.text
  }

  val prependElements = newArrayList<XmlTagChild>()
  var indent: XmlText? = null
  // Try to merge items of the same name
  val old = root.subTags.associateBy { getResourceId(it) }
  loop@ for (child in sourcePsiFile.rootTag!!.children) {
    when (child) {
      is XmlComment -> {
        if (indent != null) {
          prependElements.add(indent)
        }
        prependElements.add(child as XmlTagChild)
      }
      is XmlText -> indent = child
      is XmlTag -> {
        var subTag = child
        val mergeStrategy = subTag.getAttributeValue(MERGE_ATTR_STRATEGY)
        subTag.setAttribute(MERGE_ATTR_STRATEGY, null)
        // remove the space left by the deleted attribute
        CodeStyleManager.getInstance(project).reformat(subTag)
        val name = getResourceId(subTag)
        val replace = if (name == null) null else old[name]
        if (replace == null) {
          if (indent != null) {
            prependElements.add(indent)
          }
          subTag = root.addSubTag(subTag, false)
          prependElements.forEach {
            root.addBefore(it, subTag)
          }
          prependElements.clear()
          continue@loop
        }
        // There is an existing item with the same id. Either replace it  or preserve it depending on the "templateMergeStrategy" attribute.
        // If that attribute does not exist, default to preserving it.

        // Let's say you've used the activity wizard once, and it  emits some configuration parameter as a resource that
        // it depends on, say "padding". Then the user goes and  tweaks the padding to some other number.
        // Now running the wizard a *second* time for some new activity, we should NOT go and set the value back to the template's default!
        when {
          MERGE_ATTR_STRATEGY_REPLACE == mergeStrategy -> {
            val newChild = replace.replace(child)
            // When we're replacing, the line is probably already indented. Skip the initial indent
            if (newChild.prevSibling is XmlText && prependElements[0] is XmlText) {
              prependElements.removeAt(0)
              // If we're adding something we'll need a newline/indent after it
              if (prependElements.isNotEmpty()) {
                prependElements.add(indent)
              }
            }
            for (element in prependElements) {
              root.addBefore(element, newChild)
            }
          }
          MERGE_ATTR_STRATEGY_PRESERVE == mergeStrategy -> {
            // Preserve the existing value.
          }
          replace.text.trim() == child.text.trim() -> {
            // There are no differences, do not issue a warning.
          }
          else -> // No explicit directive given, preserve the original value by default.
            warningsToAdd.add("Ignoring conflict for the value: $name wanted: \"%${child.text}\" but it already is: \"%${replace.text}\" in the file: $fileName")
        }
        prependElements.clear()
      }
    }
  }

  return targetPsiFile.text
}

/**
 * Merges the given manifest fragment into the given manifest file
 */
private fun mergeManifest(moduleRoot: File, targetManifest: File,
                          targetXml: String, mergeText: String): MergingReport? {
  try {
    val isMasterManifest = FileUtil.filesEqual(moduleRoot, targetManifest.parentFile)

    val tempFile2 = File(targetManifest.parentFile, "nevercreated.xml")
    val logger = StdLogger(StdLogger.Level.INFO)
    return ManifestMerger2.newMerger(targetManifest, logger, ManifestMerger2.MergeType.APPLICATION)
      .withFeatures(ManifestMerger2.Invoker.Feature.EXTRACT_FQCNS,
                    ManifestMerger2.Invoker.Feature.HANDLE_VALUE_CONFLICTS_AUTOMATICALLY,
                    ManifestMerger2.Invoker.Feature.NO_PLACEHOLDER_REPLACEMENT)
      .addFlavorAndBuildTypeManifest(tempFile2)
      .asType(if (isMasterManifest) XmlDocument.Type.MAIN else XmlDocument.Type.OVERLAY)
      .withFileStreamProvider(object : ManifestMerger2.FileStreamProvider() {
        @Throws(FileNotFoundException::class)
        override fun getInputStream(file: File): InputStream {
          val text = if (FileUtil.filesEqual(file, targetManifest)) targetXml else mergeText
          return ByteArrayInputStream(text.toByteArray(Charsets.UTF_8))
        }
      })
      .merge()
  }
  catch (e: ManifestMerger2.MergeFailureException) {
    LOG.warn(e)
    return null
  }
}

private fun getResourceId(tag: XmlTag): String? = tag.getAttributeValue(ATTR_NAME) ?: tag.getAttributeValue(ATTR_ID)

/**
 * Wraps the given strings in the standard conflict syntax
 */
private fun wrapWithMergeConflict(original: String, added: String): String =
  "<<<<<<< Original\n$original\n=======\n$added>>>>>>> Added\n"
