/*
 * Copyright (C) 2022 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

import com.android.aapt.Resources

internal fun Resources.ResourceTable.entriesSequence(): Sequence<EntryWrapper> = sequence {
    for (resourcePackage in packageList) {
        for (resourceType in resourcePackage.typeList) {
            for (resourceEntry in resourceType.entryList) {
                val id = toIdentifier(resourcePackage, resourceType, resourceEntry)
                yield(
                    EntryWrapper(id, resourcePackage.packageName, resourceType.name, resourceEntry)
                )
            }
        }
    }
}

internal fun Resources.ResourceTable.nullOutEntriesWithIds(ids: List<Int>)
    : Resources.ResourceTable {
    return nullOutEntriesWithIds(ids, false)
}

internal fun Resources.ResourceTable.nullOutEntriesWithIds(
    ids: List<Int>, pruneResourceNames: Boolean): Resources.ResourceTable {
    if (ids.isEmpty()) {
        return this
    }
    val packageMappings = calculatePackageMappings(ids)
    val tableBuilder = this.toBuilder()
    tableBuilder.packageBuilderList.forEach {
        val typeMappings = packageMappings[it.packageId.id]
        if (typeMappings != null) {
            it.typeBuilderList.forEach { type ->
                val entryList = typeMappings[type.typeId.id]
                if (entryList != null) {
                    type.entryBuilderList.forEach { entry ->
                        if (entryList.contains(entry.entryId.id)) {
                            entry.clearConfigValue()
                            if (pruneResourceNames) {
                                entry.clearName();
                            }
                            if (entry.hasOverlayableItem()) {
                                entry.clearOverlayableItem()
                            }
                        }
                    }
                }
            }
        }
    }
    return tableBuilder.build()
}

private fun calculatePackageMappings(ids: List<Int>): MutableMap<Int, Map<Int, List<Int>>> {
    val sortedIds = ids.sorted()
    val packageMapping = mutableMapOf<Int, Map<Int, List<Int>>>()
    var typeMapping = mutableMapOf<Int, List<Int>>()
    var entryList = mutableListOf<Int>()
    var oldPackageId = -1
    var oldTypeId = -1
    for (value in sortedIds) {
        val packageId = packageIdFromIdentifier(value)
        val typeId = typeIdFromIdentifier(value)
        val entryId = entryIdFromIdentifier(value)
        if (packageId != oldPackageId) {
            typeMapping = mutableMapOf()
            packageMapping.put(packageId, typeMapping)
            oldPackageId = packageId
            oldTypeId = -1
        }
        if (typeId != oldTypeId) {
            entryList = mutableListOf()
            typeMapping.put(typeId, entryList)
            oldTypeId = typeId
        }
        entryList.add(entryId)
    }
    return packageMapping
}

internal data class EntryWrapper(
    val id: Int,
    val packageName: String,
    val type: String,
    val entry: Resources.Entry
)

fun toIdentifier(
    resourcePackage: Resources.Package,
    type: Resources.Type,
    entry: Resources.Entry
): Int =
    (resourcePackage.packageId.id shl 24) or (type.typeId.id shl 16) or entry.entryId.id

private fun packageIdFromIdentifier(
    identifier: Int
): Int =
    identifier shr 24

private fun typeIdFromIdentifier(
    identifier: Int
): Int =
    (identifier and 0x00FF0000) shr 16

private fun entryIdFromIdentifier(
    identifier: Int
): Int =
    (identifier and 0x0000FFFF)


