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

#include "ConfigDescription.h"
#include "ResourceTable.h"
#include "split/TableSplitter.h"

#include <algorithm>
#include <map>
#include <set>
#include <unordered_map>
#include <vector>

namespace aapt {

using ConfigClaimedMap = std::unordered_map<ResourceConfigValue*, bool>;
using ConfigDensityGroups = std::map<ConfigDescription, std::vector<ResourceConfigValue*>>;

static ConfigDescription copyWithoutDensity(const ConfigDescription& config) {
    ConfigDescription withoutDensity = config;
    withoutDensity.density = 0;
    return withoutDensity;
}

/**
 * Selects values that match exactly the constraints given.
 */
class SplitValueSelector {
public:
    explicit SplitValueSelector(const SplitConstraints& constraints) {
        for (const ConfigDescription& config : constraints.configs) {
            if (config.density == 0) {
                mDensityIndependentConfigs.insert(config);
            } else {
                mDensityDependentConfigToDensityMap[copyWithoutDensity(config)] = config.density;
            }
        }
    }

    std::vector<ResourceConfigValue*> selectValues(const ConfigDensityGroups& densityGroups,
                                                   ConfigClaimedMap* claimedValues) {
        std::vector<ResourceConfigValue*> selected;

        // Select the regular values.
        for (auto& entry : *claimedValues) {
            // Check if the entry has a density.
            ResourceConfigValue* configValue = entry.first;
            if (configValue->config.density == 0 && !entry.second) {
                // This is still available.
                if (mDensityIndependentConfigs.find(configValue->config) !=
                        mDensityIndependentConfigs.end()) {
                    selected.push_back(configValue);

                    // Mark the entry as taken.
                    entry.second = true;
                }
            }
        }

        // Now examine the densities
        for (auto& entry : densityGroups) {
            // We do not care if the value is claimed, since density values can be
            // in multiple splits.
            const ConfigDescription& config = entry.first;
            const std::vector<ResourceConfigValue*>& relatedValues = entry.second;

            auto densityValueIter = mDensityDependentConfigToDensityMap.find(config);
            if (densityValueIter != mDensityDependentConfigToDensityMap.end()) {
                // Select the best one!
                ConfigDescription targetDensity = config;
                targetDensity.density = densityValueIter->second;

                ResourceConfigValue* bestValue = nullptr;
                for (ResourceConfigValue* thisValue : relatedValues) {
                    if (!bestValue ||
                            thisValue->config.isBetterThan(bestValue->config, &targetDensity)) {
                        bestValue = thisValue;
                    }

                    // When we select one of these, they are all claimed such that the base
                    // doesn't include any anymore.
                    (*claimedValues)[thisValue] = true;
                }
                assert(bestValue);
                selected.push_back(bestValue);
            }
        }
        return selected;
    }

private:
    std::set<ConfigDescription> mDensityIndependentConfigs;
    std::map<ConfigDescription, uint16_t> mDensityDependentConfigToDensityMap;
};

/**
 * Marking non-preferred densities as claimed will make sure the base doesn't include them,
 * leaving only the preferred density behind.
 */
static void markNonPreferredDensitiesAsClaimed(uint16_t preferredDensity,
                                               const ConfigDensityGroups& densityGroups,
                                               ConfigClaimedMap* configClaimedMap) {
    for (auto& entry : densityGroups) {
        const ConfigDescription& config = entry.first;
        const std::vector<ResourceConfigValue*>& relatedValues = entry.second;

        ConfigDescription targetDensity = config;
        targetDensity.density = preferredDensity;
        ResourceConfigValue* bestValue = nullptr;
        for (ResourceConfigValue* thisValue : relatedValues) {
            if (!bestValue) {
                bestValue = thisValue;
            } else if (thisValue->config.isBetterThan(bestValue->config, &targetDensity)) {
                // Claim the previous value so that it is not included in the base.
                (*configClaimedMap)[bestValue] = true;
                bestValue = thisValue;
            } else {
                // Claim this value so that it is not included in the base.
                (*configClaimedMap)[thisValue] = true;
            }
        }
        assert(bestValue);
    }
}

bool TableSplitter::verifySplitConstraints(IAaptContext* context) {
    bool error = false;
    for (size_t i = 0; i < mSplitConstraints.size(); i++) {
        for (size_t j = i + 1; j < mSplitConstraints.size(); j++) {
            for (const ConfigDescription& config : mSplitConstraints[i].configs) {
                if (mSplitConstraints[j].configs.find(config) !=
                        mSplitConstraints[j].configs.end()) {
                    context->getDiagnostics()->error(DiagMessage() << "config '" << config
                                                     << "' appears in multiple splits, "
                                                     << "target split ambiguous");
                    error = true;
                }
            }
        }
    }
    return !error;
}

void TableSplitter::splitTable(ResourceTable* originalTable) {
    const size_t splitCount = mSplitConstraints.size();
    for (auto& pkg : originalTable->packages) {
        // Initialize all packages for splits.
        for (size_t idx = 0; idx < splitCount; idx++) {
            ResourceTable* splitTable = mSplits[idx].get();
            splitTable->createPackage(pkg->name, pkg->id);
        }

        for (auto& type : pkg->types) {
            if (type->type == ResourceType::kMipmap) {
                // Always keep mipmaps.
                continue;
            }

            for (auto& entry : type->entries) {
                if (mConfigFilter) {
                    // First eliminate any resource that we definitely don't want.
                    for (std::unique_ptr<ResourceConfigValue>& configValue : entry->values) {
                        if (!mConfigFilter->match(configValue->config)) {
                            // null out the entry. We will clean up and remove nulls at the end
                            // for performance reasons.
                            configValue.reset();
                        }
                    }
                }

                // Organize the values into two separate buckets. Those that are density-dependent
                // and those that are density-independent.
                // One density technically matches all density, it's just that some densities
                // match better. So we need to be aware of the full set of densities to make this
                // decision.
                ConfigDensityGroups densityGroups;
                ConfigClaimedMap configClaimedMap;
                for (const std::unique_ptr<ResourceConfigValue>& configValue : entry->values) {
                    if (configValue) {
                        configClaimedMap[configValue.get()] = false;

                        if (configValue->config.density != 0) {
                            // Create a bucket for this density-dependent config.
                            densityGroups[copyWithoutDensity(configValue->config)]
                                          .push_back(configValue.get());
                        }
                    }
                }

                // First we check all the splits. If it doesn't match one of the splits, we
                // leave it in the base.
                for (size_t idx = 0; idx < splitCount; idx++) {
                    const SplitConstraints& splitConstraint = mSplitConstraints[idx];
                    ResourceTable* splitTable = mSplits[idx].get();

                    // Select the values we want from this entry for this split.
                    SplitValueSelector selector(splitConstraint);
                    std::vector<ResourceConfigValue*> selectedValues =
                            selector.selectValues(densityGroups, &configClaimedMap);

                    // No need to do any work if we selected nothing.
                    if (!selectedValues.empty()) {
                        // Create the same resource structure in the split. We do this lazily
                        // because we might not have actual values for each type/entry.
                        ResourceTablePackage* splitPkg = splitTable->findPackage(pkg->name);
                        ResourceTableType* splitType = splitPkg->findOrCreateType(type->type);
                        if (!splitType->id) {
                            splitType->id = type->id;
                            splitType->symbolStatus = type->symbolStatus;
                        }

                        ResourceEntry* splitEntry = splitType->findOrCreateEntry(entry->name);
                        if (!splitEntry->id) {
                            splitEntry->id = entry->id;
                            splitEntry->symbolStatus = entry->symbolStatus;
                        }

                        // Copy the selected values into the new Split Entry.
                        for (ResourceConfigValue* configValue : selectedValues) {
                            ResourceConfigValue* newConfigValue = splitEntry->findOrCreateValue(
                                    configValue->config, configValue->product);
                            newConfigValue->value = std::unique_ptr<Value>(
                                    configValue->value->clone(&splitTable->stringPool));
                        }
                    }
                }

                if (mPreferredDensity) {
                    markNonPreferredDensitiesAsClaimed(mPreferredDensity.value(),
                                                       densityGroups,
                                                       &configClaimedMap);
                }

                // All splits are handled, now check to see what wasn't claimed and remove
                // whatever exists in other splits.
                for (std::unique_ptr<ResourceConfigValue>& configValue : entry->values) {
                    if (configValue && configClaimedMap[configValue.get()]) {
                        // Claimed, remove from base.
                        configValue.reset();
                    }
                }

                // Now erase all nullptrs.
                entry->values.erase(
                        std::remove(entry->values.begin(), entry->values.end(), nullptr),
                        entry->values.end());
            }
        }
    }
}

} // namespace aapt
