/*
 * 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 "util/Util.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;
                    }
                }
                assert(bestValue);

                // When we select one of these, they are all claimed such that the base
                // doesn't include any anymore.
                (*claimedValues)[bestValue] = true;
                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
