/*
 * Copyright (C) 2015 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 "link/Linkers.h"

#include <algorithm>

#include "android-base/logging.h"

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

using android::ConfigDescription;

namespace aapt {

bool ShouldGenerateVersionedResource(const ResourceEntry* entry,
                                     const ConfigDescription& config,
                                     const ApiVersion sdk_version_to_generate) {
  // We assume the caller is trying to generate a version greater than the current configuration.
  CHECK(sdk_version_to_generate > config.sdkVersion);
  return sdk_version_to_generate < FindNextApiVersionForConfig(entry, config);
}

ApiVersion FindNextApiVersionForConfig(const ResourceEntry* entry,
                                       const ConfigDescription& config) {
  const auto end_iter = entry->values.end();
  auto iter = entry->values.begin();
  for (; iter != end_iter; ++iter) {
    if ((*iter)->config == config) {
      break;
    }
  }

  // The source config came from this list, so it should be here.
  CHECK(iter != entry->values.end());
  ++iter;

  // The next configuration either only varies in sdkVersion, or it is completely different
  // and therefore incompatible. If it is incompatible, we must generate the versioned resource.

  // NOTE: The ordering of configurations takes sdkVersion as higher precedence than other
  // qualifiers, so we need to iterate through the entire list to be sure there
  // are no higher sdk level versions of this resource.
  ConfigDescription temp_config(config);
  for (; iter != end_iter; ++iter) {
    temp_config.sdkVersion = (*iter)->config.sdkVersion;
    if (temp_config == (*iter)->config) {
      // The two configs are the same, return the sdkVersion.
      return (*iter)->config.sdkVersion;
    }
  }

  // Didn't find another config with a different sdk version, so return the highest possible value.
  return std::numeric_limits<ApiVersion>::max();
}

bool AutoVersioner::Consume(IAaptContext* context, ResourceTable* table) {
  TRACE_NAME("AutoVersioner::Consume");
  CloningValueTransformer cloner(&table->string_pool);
  for (auto& package : table->packages) {
    for (auto& type : package->types) {
      if (type->named_type.type != ResourceType::kStyle) {
        continue;
      }

      for (auto& entry : type->entries) {
        for (size_t i = 0; i < entry->values.size(); i++) {
          ResourceConfigValue* config_value = entry->values[i].get();
          if (config_value->config.sdkVersion >= SDK_LOLLIPOP_MR1) {
            // If this configuration is only used on L-MR1 then we don't need
            // to do anything since we use private attributes since that
            // version.
            continue;
          }

          if (Style* style = ValueCast<Style>(config_value->value.get())) {
            std::optional<ApiVersion> min_sdk_stripped;
            std::vector<Style::Entry> stripped;

            auto iter = style->entries.begin();
            while (iter != style->entries.end()) {
              CHECK(bool(iter->key.id)) << "IDs must be assigned and linked";

              // Find the SDK level that is higher than the configuration
              // allows.
              const ApiVersion sdk_level = FindAttributeSdkLevel(iter->key.id.value());
              if (sdk_level > std::max<ApiVersion>(config_value->config.sdkVersion, 1)) {
                // Record that we are about to strip this.
                stripped.emplace_back(std::move(*iter));

                // We use the smallest SDK level to generate the new style.
                if (min_sdk_stripped) {
                  min_sdk_stripped = std::min(min_sdk_stripped.value(), sdk_level);
                } else {
                  min_sdk_stripped = sdk_level;
                }

                // Erase this from this style.
                iter = style->entries.erase(iter);
                continue;
              }
              ++iter;
            }

            if (min_sdk_stripped && !stripped.empty()) {
              // We found attributes from a higher SDK level. Check that
              // there is no other defined resource for the version we want to
              // generate.
              if (ShouldGenerateVersionedResource(entry.get(),
                                                  config_value->config,
                                                  min_sdk_stripped.value())) {
                // Let's create a new Style for this versioned resource.
                ConfigDescription new_config(config_value->config);
                new_config.sdkVersion = static_cast<uint16_t>(min_sdk_stripped.value());

                std::unique_ptr<Style> new_style(style->Transform(cloner));
                new_style->SetComment(style->GetComment());
                new_style->SetSource(style->GetSource());

                // Move the previously stripped attributes into this style.
                new_style->entries.insert(
                    new_style->entries.end(),
                    std::make_move_iterator(stripped.begin()),
                    std::make_move_iterator(stripped.end()));

                // Insert the new Resource into the correct place.
                entry->FindOrCreateValue(new_config, {})->value = std::move(new_style);
              }
            }
          }
        }
      }
    }
  }
  return true;
}

}  // namespace aapt
