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

package com.google.gerrit.server.index;

import com.google.common.collect.ImmutableSet;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.inject.Inject;
import com.google.inject.ProvisionException;
import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Named;
import com.google.inject.name.Names;

import org.eclipse.jgit.lib.Config;

import java.util.Collection;
import java.util.Map;
import java.util.Set;

@Singleton
public class SingleVersionModule extends LifecycleModule {
  public static final String SINGLE_VERSIONS = "IndexModule/SingleVersions";

  private final Map<String, Integer> singleVersions;

  public SingleVersionModule(Map<String, Integer> singleVersions) {
    this.singleVersions = singleVersions;
  }

  @Override
  public void configure() {
    listener().to(SingleVersionListener.class);
    bind(new TypeLiteral<Map<String, Integer>>() {})
        .annotatedWith(Names.named(SINGLE_VERSIONS))
        .toInstance(singleVersions);
  }

  @Singleton
  public static class SingleVersionListener implements LifecycleListener {
    private final Set<String> disabled;
    private final Collection<IndexDefinition<?, ?, ?>> defs;
    private final Map<String, Integer> singleVersions;

    @Inject
    SingleVersionListener(
        @GerritServerConfig Config cfg,
        Collection<IndexDefinition<?, ?, ?>> defs,
        @Named(SINGLE_VERSIONS) Map<String, Integer> singleVersions) {
      this.defs = defs;
      this.singleVersions = singleVersions;

      disabled = ImmutableSet.copyOf(
          cfg.getStringList("index", null, "testDisable"));
    }

    @Override
    public void start() {
      for (IndexDefinition<?, ?, ?> def : defs) {
        start(def);
      }
    }

    private <K, V, I extends Index<K, V>> void start(
        IndexDefinition<K, V, I> def) {
      if (disabled.contains(def.getName())) {
        return;
      }
      Schema<V> schema;
      Integer v = singleVersions.get(def.getName());
      if (v == null) {
        schema = def.getLatest();
      } else {
        schema = def.getSchemas().get(v);
        if (schema == null) {
          throw new ProvisionException(String.format(
                "Unrecognized %s schema version: %s", def.getName(), v));
        }
      }
      I index = def.getIndexFactory().create(schema);
      def.getIndexCollection().setSearchIndex(index);
      def.getIndexCollection().addWriteIndex(index);
    }

    @Override
    public void stop() {
      // Do nothing; indexes are closed by IndexCollection.
    }
  }
}