/*
 * Copyright (C) 2014 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 "RuleGenerator.h"

#include <algorithm>
#include <cmath>
#include <vector>
#include <androidfw/ResourceTypes.h>

using namespace android;

namespace split {

// Calculate the point at which the density selection changes between l and h.
static inline int findMid(int l, int h) {
    double root = sqrt((h*h) + (8*l*h));
    return (double(-h) + root) / 2.0;
}

sp<Rule> RuleGenerator::generateDensity(const Vector<int>& allDensities, size_t index) {
    sp<Rule> densityRule = new Rule();
    densityRule->op = Rule::AND_SUBRULES;

    const bool anyDensity = allDensities[index] == ResTable_config::DENSITY_ANY;
    sp<Rule> any = new Rule();
    any->op = Rule::EQUALS;
    any->key = Rule::SCREEN_DENSITY;
    any->longArgs.add((int)ResTable_config::DENSITY_ANY);
    any->negate = !anyDensity;
    densityRule->subrules.add(any);

    if (!anyDensity) {
        if (index > 0) {
            sp<Rule> gt = new Rule();
            gt->op = Rule::GREATER_THAN;
            gt->key = Rule::SCREEN_DENSITY;
            gt->longArgs.add(findMid(allDensities[index - 1], allDensities[index]) - 1);
            densityRule->subrules.add(gt);
        }

        if (index + 1 < allDensities.size() && allDensities[index + 1] != ResTable_config::DENSITY_ANY) {
            sp<Rule> lt = new Rule();
            lt->op = Rule::LESS_THAN;
            lt->key = Rule::SCREEN_DENSITY;
            lt->longArgs.add(findMid(allDensities[index], allDensities[index + 1]));
            densityRule->subrules.add(lt);
        }
    }
    return densityRule;
}

sp<Rule> RuleGenerator::generateAbi(const Vector<abi::Variant>& splitAbis, size_t index) {
    const abi::Variant thisAbi = splitAbis[index];
    const Vector<abi::Variant>& familyVariants = abi::getVariants(abi::getFamily(thisAbi));

    Vector<abi::Variant>::const_iterator start =
            std::find(familyVariants.begin(), familyVariants.end(), thisAbi);

    Vector<abi::Variant>::const_iterator end = familyVariants.end();
    if (index + 1 < splitAbis.size()) {
        end = std::find(start, familyVariants.end(), splitAbis[index + 1]);
    }

    sp<Rule> abiRule = new Rule();
    abiRule->op = Rule::CONTAINS_ANY;
    abiRule->key = Rule::NATIVE_PLATFORM;
    while (start != end) {
        abiRule->stringArgs.add(String8(abi::toString(*start)));
        ++start;
    }
    return abiRule;
}

sp<Rule> RuleGenerator::generate(const SortedVector<SplitDescription>& group, size_t index) {
    sp<Rule> rootRule = new Rule();
    rootRule->op = Rule::AND_SUBRULES;

    if (group[index].config.locale != 0) {
        sp<Rule> locale = new Rule();
        locale->op = Rule::EQUALS;
        locale->key = Rule::LANGUAGE;
        char str[RESTABLE_MAX_LOCALE_LEN];
        group[index].config.getBcp47Locale(str);
        locale->stringArgs.add(String8(str));
        rootRule->subrules.add(locale);
    }

    if (group[index].config.sdkVersion != 0) {
        sp<Rule> sdk = new Rule();
        sdk->op = Rule::GREATER_THAN;
        sdk->key = Rule::SDK_VERSION;
        sdk->longArgs.add(group[index].config.sdkVersion - 1);
        rootRule->subrules.add(sdk);
    }

    if (group[index].config.density != 0) {
        size_t densityIndex = 0;
        Vector<int> allDensities;
        allDensities.add(group[index].config.density);

        const size_t groupSize = group.size();
        for (size_t i = 0; i < groupSize; i++) {
            if (group[i].config.density != group[index].config.density) {
                // This group differs by density.
                allDensities.clear();
                for (size_t j = 0; j < groupSize; j++) {
                    allDensities.add(group[j].config.density);
                }
                densityIndex = index;
                break;
            }
        }
        rootRule->subrules.add(generateDensity(allDensities, densityIndex));
    }

    if (group[index].abi != abi::Variant_none) {
        size_t abiIndex = 0;
        Vector<abi::Variant> allVariants;
        allVariants.add(group[index].abi);

        const size_t groupSize = group.size();
        for (size_t i = 0; i < groupSize; i++) {
            if (group[i].abi != group[index].abi) {
                // This group differs by ABI.
                allVariants.clear();
                for (size_t j = 0; j < groupSize; j++) {
                    allVariants.add(group[j].abi);
                }
                abiIndex = index;
                break;
            }
        }
        rootRule->subrules.add(generateAbi(allVariants, abiIndex));
    }

    return rootRule;
}

} // namespace split
