/*
 * 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 "optimize/VersionCollapser.h"

#include <algorithm>
#include <vector>

#include "ResourceTable.h"
#include "trace/TraceBuffer.h"

using android::ConfigDescription;

namespace aapt {

template <typename Iterator, typename Pred>
class FilterIterator {
 public:
  FilterIterator(Iterator begin, Iterator end, Pred pred = Pred())
      : current_(begin), end_(end), pred_(pred) {
    Advance();
  }

  bool HasNext() { return current_ != end_; }

  Iterator NextIter() {
    Iterator iter = current_;
    ++current_;
    Advance();
    return iter;
  }

  typename Iterator::reference Next() { return *NextIter(); }

 private:
  void Advance() {
    for (; current_ != end_; ++current_) {
      if (pred_(*current_)) {
        return;
      }
    }
  }

  Iterator current_, end_;
  Pred pred_;
};

template <typename Iterator, typename Pred>
FilterIterator<Iterator, Pred> make_filter_iterator(Iterator begin,
                                                    Iterator end = Iterator(),
                                                    Pred pred = Pred()) {
  return FilterIterator<Iterator, Pred>(begin, end, pred);
}

/**
 * Every Configuration with an SDK version specified that is less than minSdk will be removed. The
 * exception is when there is no exact matching resource for the minSdk. The next smallest one will
 * be kept.
 */
static void CollapseVersions(int min_sdk, ResourceEntry* entry) {
  // First look for all sdks less than minSdk.
  for (auto iter = entry->values.rbegin(); iter != entry->values.rend();
       ++iter) {
    // Check if the item was already marked for removal.
    if (!(*iter)) {
      continue;
    }

    const ConfigDescription& config = (*iter)->config;
    if (config.sdkVersion <= min_sdk) {
      // This is the first configuration we've found with a smaller or equal SDK level to the
      // minimum. We MUST keep this one, but remove all others we find, which get overridden by this
      // one.

      ConfigDescription config_without_sdk = config.CopyWithoutSdkVersion();
      auto pred = [&](const std::unique_ptr<ResourceConfigValue>& val) -> bool {
        // Check that the value hasn't already been marked for removal.
        if (!val) {
          return false;
        }

        // Only return Configs that differ in SDK version.
        config_without_sdk.sdkVersion = val->config.sdkVersion;
        return config_without_sdk == val->config &&
               val->config.sdkVersion <= min_sdk;
      };

      // Remove the rest that match.
      auto filter_iter =
          make_filter_iterator(iter + 1, entry->values.rend(), pred);
      while (filter_iter.HasNext()) {
        filter_iter.Next() = {};
      }
    }
  }

  // Now erase the nullptr values.
  entry->values.erase(
      std::remove_if(entry->values.begin(), entry->values.end(),
                     [](const std::unique_ptr<ResourceConfigValue>& val)
                         -> bool { return val == nullptr; }),
      entry->values.end());

  // Strip the version qualifiers for every resource with version <= minSdk. This will ensure that
  // the resource entries are all packed together in the same ResTable_type struct and take up less
  // space in the resources.arsc table.
  bool modified = false;
  for (std::unique_ptr<ResourceConfigValue>& config_value : entry->values) {
    if (config_value->config.sdkVersion != 0 &&
        config_value->config.sdkVersion <= min_sdk) {
      // Override the resource with a Configuration without an SDK.
      std::unique_ptr<ResourceConfigValue> new_value =
          util::make_unique<ResourceConfigValue>(
              config_value->config.CopyWithoutSdkVersion(),
              config_value->product);
      new_value->value = std::move(config_value->value);
      config_value = std::move(new_value);

      modified = true;
    }
  }

  if (modified) {
    // We've modified the keys (ConfigDescription) by changing the sdkVersion to 0. We MUST re-sort
    // to ensure ordering guarantees hold.
    std::sort(entry->values.begin(), entry->values.end(),
              [](const std::unique_ptr<ResourceConfigValue>& a,
                 const std::unique_ptr<ResourceConfigValue>& b) -> bool {
                return a->config.compare(b->config) < 0;
              });
  }
}

bool VersionCollapser::Consume(IAaptContext* context, ResourceTable* table) {
  TRACE_NAME("VersionCollapser::Consume");
  const int min_sdk = context->GetMinSdkVersion();
  for (auto& package : table->packages) {
    for (auto& type : package->types) {
      for (auto& entry : type->entries) {
        CollapseVersions(min_sdk, entry.get());
      }
    }
  }
  return true;
}

}  // namespace aapt
