// Copyright (C) 2009 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.pgm.init;

import static com.google.gerrit.common.FileUtil.chmod;
import static com.google.gerrit.pgm.init.api.InitUtil.die;
import static com.google.gerrit.pgm.init.api.InitUtil.extract;
import static com.google.gerrit.pgm.init.api.InitUtil.mkdir;
import static com.google.gerrit.pgm.init.api.InitUtil.savePublic;
import static com.google.gerrit.pgm.init.api.InitUtil.version;

import com.google.common.io.Files;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.pgm.init.api.ConsoleUI;
import com.google.gerrit.pgm.init.api.InitFlags;
import com.google.gerrit.pgm.init.api.InitStep;
import com.google.gerrit.pgm.init.api.Section;
import com.google.gerrit.pgm.init.api.Section.Factory;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.mail.OutgoingEmail;
import com.google.inject.Binding;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.TypeLiteral;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/** Initialize (or upgrade) an existing site. */
public class SitePathInitializer {
  private final ConsoleUI ui;
  private final InitFlags flags;
  private final SitePaths site;
  private final List<InitStep> steps;
  private final Factory sectionFactory;
  private final SecureStoreInitData secureStoreInitData;

  @Inject
  public SitePathInitializer(final Injector injector, final ConsoleUI ui,
      final InitFlags flags, final SitePaths site,
      final Section.Factory sectionFactory,
      final @Nullable SecureStoreInitData secureStoreInitData) {
    this.ui = ui;
    this.flags = flags;
    this.site = site;
    this.sectionFactory = sectionFactory;
    this.secureStoreInitData = secureStoreInitData;
    this.steps = stepsOf(injector);
  }

  public void run() throws Exception {
    ui.header("Gerrit Code Review %s", version());

    if (site.isNew) {
      if (!ui.yesno(true, "Create '%s'", site.site_path.getCanonicalPath())) {
        throw die("aborted by user");
      }
      if (!site.site_path.isDirectory() && !site.site_path.mkdirs()) {
        throw die("Cannot make directory " + site.site_path);
      }
      flags.deleteOnFailure = true;
    }

    mkdir(site.bin_dir);
    mkdir(site.etc_dir);
    mkdir(site.lib_dir);
    mkdir(site.tmp_dir);
    mkdir(site.logs_dir);
    mkdir(site.mail_dir);
    mkdir(site.static_dir);
    mkdir(site.plugins_dir);
    mkdir(site.data_dir);

    for (InitStep step : steps) {
      if (step instanceof InitPlugins
          && flags.skipPlugins) {
        continue;
      }
      step.run();
    }

    saveSecureStore();
    savePublic(flags.cfg);

    extract(site.gerrit_sh, getClass(), "gerrit.sh");
    chmod(0755, site.gerrit_sh);
    chmod(0700, site.tmp_dir);

    extractMailExample("Abandoned.vm");
    extractMailExample("ChangeFooter.vm");
    extractMailExample("ChangeSubject.vm");
    extractMailExample("Comment.vm");
    extractMailExample("CommentFooter.vm");
    extractMailExample("Footer.vm");
    extractMailExample("Merged.vm");
    extractMailExample("MergeFail.vm");
    extractMailExample("NewChange.vm");
    extractMailExample("RegisterNewEmail.vm");
    extractMailExample("ReplacePatchSet.vm");
    extractMailExample("Restored.vm");
    extractMailExample("Reverted.vm");

    if (!ui.isBatch()) {
      System.err.println();
    }
  }

  public void postRun(Injector injector) throws Exception {
    for (InitStep step : steps) {
      if (step instanceof InitPlugins
          && flags.skipPlugins) {
        continue;
      }
      injector.injectMembers(step);
      step.postRun();
    }
  }

  private void saveSecureStore() throws IOException {
    if (secureStoreInitData != null) {
      File dst = new File(site.lib_dir, secureStoreInitData.jarFile.getName());
      Files.copy(secureStoreInitData.jarFile, dst);
      Section gerritSection = sectionFactory.get("gerrit", null);
      gerritSection.set("secureStoreClass", secureStoreInitData.className);
    }
  }

  private void extractMailExample(String orig) throws Exception {
    File ex = new File(site.mail_dir, orig + ".example");
    extract(ex, OutgoingEmail.class, orig);
    chmod(0444, ex);
  }

  private static List<InitStep> stepsOf(final Injector injector) {
    final ArrayList<InitStep> r = new ArrayList<>();
    for (Binding<InitStep> b : all(injector)) {
      r.add(b.getProvider().get());
    }
    return r;
  }

  private static List<Binding<InitStep>> all(final Injector injector) {
    return injector.findBindingsByType(new TypeLiteral<InitStep>() {});
  }
}
