/*
 * Copyright (C) 2020 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.android.build.shrinker.graph

import com.android.aapt.Resources
import com.android.aapt.Resources.Entry
import com.android.aapt.Resources.FileReference
import com.android.aapt.Resources.FileReference.Type.PROTO_XML
import com.android.aapt.Resources.Reference
import com.android.aapt.Resources.ResourceTable
import com.android.aapt.Resources.XmlAttribute
import com.android.aapt.Resources.XmlElement
import com.android.aapt.Resources.XmlNode
import com.android.build.shrinker.ResourceShrinkerModel
import com.android.build.shrinker.entriesSequence
import com.android.ide.common.resources.usage.ResourceUsageModel
import com.android.ide.common.resources.usage.ResourceUsageModel.Resource
import com.android.ide.common.resources.usage.WebTokenizers
import com.android.resources.ResourceType
import com.android.utils.SdkUtils.IMAGE_EXTENSIONS
import com.google.common.base.Ascii
import java.io.IOException
import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.nio.file.Path

/**
 * Builds resources graph starting from each resource in resource table in proto format and follow
 * all references to other resources inside inlined values and external files from res/ folder.
 *
 * <p>Supports external files in the following formats:
 * <ul>
 *     <li>XML files compiled to proto format;
 *     <li>HTML, CSS, JS files inside res/raw folder;
 *     <li>Unknown files inside res/raw folder (only looks for 'android_res/<type>/<name>' pattern);
 * </ul>
 *
 * <p>As ID resources don't specify parent-child relations between resources but are just
 * identifiers for a resource or some part of the resource we don't gather them as references to
 * examined resource.
 *
 * @param resourceRoot path to <module>/res/ folder.
 * @param resourceTable path to resource table in proto format.
 */
class ProtoResourcesGraphBuilder(
    private val resourceRoot: ResFolderFileTree,
    private val resourceTableProducer: (ResourceShrinkerModel) -> ResourceTable
) : ResourcesGraphBuilder {

    constructor(resourceRootPath: Path, resourceTablePath: Path) : this(
        object : ResFolderFileTree {
            override fun getEntryByName(pathInRes: String): ByteArray {
                val lazyVal : ByteArray by lazy {
                    Files.readAllBytes(resourceRootPath.resolve(pathInRes))
                }
                return lazyVal
            }
        },
        { model -> model.readResourceTable(resourceTablePath) }
    )
    override fun buildGraph(model: ResourceShrinkerModel) {
        resourceTableProducer(model).entriesSequence()
            .map { (id, _, _, entry) ->
                model.resourceStore.getResource(id)?.let {
                    ReferencesForResourceFinder(resourceRoot, model, entry, it)
                }
            }
            .filterNotNull()
            .forEach { it.findReferences() }
    }
}
interface ResFolderFileTree {
    fun getEntryByName(pathInRes: String) : ByteArray
}

private class ReferencesForResourceFinder(
    private val resourcesRoot: ResFolderFileTree,
    private val model: ResourceShrinkerModel,
    private val entry: Entry,
    private val current: Resource
) {
    companion object {
        /**
         * 'android_res/' is a synthetic directory for resource references in URL format. For
         *  example: file:///android_res/raw/intro_page.
         */
        private const val ANDROID_RES = "android_res/"

        private const val CONSTRAINT_REFERENCED_IDS = "constraint_referenced_ids"

        private fun Reference.asItem(): Resources.Item =
            Resources.Item.newBuilder().setRef(this).build()
    }

    private val webTokenizers: WebTokenizers by lazy {
        WebTokenizers(object : WebTokenizers.WebTokensCallback {
            override fun referencedHtmlAttribute(tag: String?, attribute: String?, value: String) {
                if (attribute == "href" || attribute == "src") {
                    referencedUrl(value)
                }
            }

            override fun referencedJsString(jsString: String) {
                referencedStringFromWebContent(jsString)
            }

            override fun referencedCssUrl(url: String) {
                referencedUrl(url)
            }

            private fun referencedUrl(url: String) {
                // 1. if url contains '/' try to find resources from this web url.
                // 2. if there is no '/' it might be just relative reference to another resource.
                val resources = when {
                    url.contains('/') -> model.resourceStore.getResourcesFromWebUrl(url)
                    else ->
                        model.resourceStore.getResources(ResourceType.RAW, url.substringBefore('.'))
                }
                if (resources.isNotEmpty()) {
                    resources.forEach { current.addReference(it) }
                } else {
                    // if there is no resources found by provided url just gather this string as
                    // found inside web content to process it afterwards.
                    referencedStringFromWebContent(url)
                }
            }

            private fun referencedStringFromWebContent(string: String) {
                if (string.isNotEmpty() && string.length <= 80) {
                    model.addStringConstant(string)
                    model.isFoundWebContent = true
                }
            }
        })
    }

    fun findReferences() {
        // Walk through all values of the entry and find all Item instances that may reference
        // other resources in resource table itself or specify external files that should be
        // analyzed for references.
        entry.configValueList.asSequence()
            .map { it.value }
            .flatMap { value ->
                val compoundValue = value.compoundValue
                // compoundValue.attr and compoundValue.styleable are skipped, attr defines
                // references to ID resources only, but ID and STYLEABLE resources are not supported
                // by shrinker.
                when {
                    value.hasItem() ->
                        sequenceOf(value.item)
                    compoundValue.hasStyle() ->
                        sequenceOf(compoundValue.style.parent.asItem()) +
                                compoundValue.style.entryList.asSequence().flatMap {
                                    sequenceOf(
                                        it.item,
                                        it.key.asItem()
                                    )
                                }
                    compoundValue.hasArray() ->
                        compoundValue.array.elementList.asSequence().map { it.item }
                    compoundValue.hasPlural() ->
                        compoundValue.plural.entryList.asSequence().map { it.item }
                    else -> emptySequence()
                }
            }
            .forEach { findFromItem(it) }
    }

    private fun findFromItem(item: Resources.Item) {
        try {
            when {
                item.hasRef() -> findFromReference(item.ref)
                item.hasFile() && item.file.path.startsWith("res/") -> findFromFile(item.file)
            }
        } catch (e: IOException) {
            model.debugReporter.debug { "File '${item.file.path}' can not be processed. Skipping." }
        }
    }

    private fun findFromReference(reference: Reference) {
        // Reference object may have id of referenced resource, in this case prefer resolved id.
        // In case id is not provided try to find referenced resource by name. Name is converted
        // to resource url here, because name in resource table is not normalized to R style field
        // and to find it we need normalize it first (for example, in case name in resource table is
        // MyStyle.Child in R file it is R.style.MyStyle_child).
        val referencedResources = when {
            reference.id != 0 -> listOf(model.resourceStore.getResource(reference.id))
            reference.name.isNotEmpty() ->
                model.resourceStore.getResourcesFromUrl("@${reference.name}")
            else -> emptyList()
        }
        // IDs are not supported by shrinker for now, just skip it.
        referencedResources.asSequence()
            .filterNotNull()
            .filter { it.type != ResourceType.ID }
            .forEach { current.addReference(it) }
    }

    private fun findFromFile(file: FileReference) {
        val bytes = resourcesRoot.getEntryByName(file.path.substringAfter("res/"))
        val content: String by lazy { String(bytes, StandardCharsets.UTF_8) }
        val extension = Ascii.toLowerCase(file.path.substringAfterLast('.'))
        when {
            file.type == PROTO_XML -> fillFromXmlNode(XmlNode.parseFrom(bytes))
            extension in listOf("html", "htm") -> webTokenizers.tokenizeHtml(content)
            extension == "css" -> webTokenizers.tokenizeCss(content)
            extension == "js" -> webTokenizers.tokenizeJs(content)
            extension !in IMAGE_EXTENSIONS -> maybeAndroidResUrl(content, markAsReachable = false)
        }
    }

    private fun fillFromXmlNode(node: XmlNode) {
        // Check for possible reference as 'android_res/<type>/<name>' pattern inside element text.
        if (current.type == ResourceType.XML) {
            maybeAndroidResUrl(node.text, markAsReachable = true)
        }
        // Check special xml element <rawPathResId> which provides reference to res/raw/ apk
        // resource for wear application. Applies to all XML files for now but might be re-scoped
        // to only apply to <wearableApp> XMLs.
        maybeWearAppReference(node.element)
        node.element.attributeList.forEach { fillFromAttribute(it) }
        node.element.childList.forEach { fillFromXmlNode(it) }
    }

    private fun fillFromAttribute(attribute: XmlAttribute) {
        if (attribute.name == CONSTRAINT_REFERENCED_IDS) {
            fillFromConstraintReferencedIds(attribute.value)
        }
        if (attribute.hasCompiledItem()) {
            findFromItem(attribute.compiledItem)
        }
        // Check for possible reference as 'android_res/<type>/<name>' pattern inside attribute val.
        if (current.type == ResourceType.XML) {
            maybeAndroidResUrl(attribute.value, markAsReachable = true)
        }
    }

    private fun fillFromConstraintReferencedIds(value: String?) {
        value
            ?.split(",")
            ?.map { it.trim() }
            ?.forEach {
                model.resourceStore.getResources(ResourceType.ID, it)
                    .forEach(ResourceUsageModel::markReachable)
            }
    }

    private fun maybeAndroidResUrl(text: String, markAsReachable: Boolean) {
        findAndroidResReferencesInText(text)
            .map { it.split('/', limit = 2) }
            .filter { it.size == 2 }
            .map { (dir, fileName) ->
                Pair(
                    ResourceType.fromFolderName(dir.substringBefore('-')),
                    fileName.substringBefore('.')
                )
            }
            .filter { (type, _) -> type != null }
            .flatMap { (type, name) -> model.resourceStore.getResources(type!!, name).asSequence() }
            .forEach {
                if (markAsReachable) {
                    ResourceUsageModel.markReachable(it)
                } else {
                    current.addReference(it)
                }
            }
    }

    private fun maybeWearAppReference(element: XmlElement) {
        if (element.name == "rawPathResId") {
            val rawResourceName = element.childList
                .map { it.text }
                .joinToString(separator = "")
                .trim()

            model.resourceStore.getResources(ResourceType.RAW, rawResourceName)
                .forEach { current.addReference(it) }
        }
    }

    /**
     * Splits input text to parts that starts with 'android_res/' and returns sequence of strings
     * between 'android_res/' occurrences and first whitespace after it. This method is used instead
     * of {@link CharSequence#splitToSequence} because does not spawn full substrings between
     * 'android_res/' in memory when text is big enough.
     */
    private fun findAndroidResReferencesInText(text: String): Sequence<String> = sequence {
        var start = 0
        while (start < text.length) {
            start = text.indexOf(ANDROID_RES, start)
            if (start == -1) {
                break
            }
            var end = start + ANDROID_RES.length
            while (end < text.length && !Character.isWhitespace(text[end])) {
                end++
            }
            yield(text.substring(start + ANDROID_RES.length, end))
            start = end
        }
    }
}
