// 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.InitUtil.die;
import static com.google.gerrit.pgm.init.InitUtil.extract;
import static com.google.gerrit.pgm.init.InitUtil.mkdir;
import static com.google.gerrit.pgm.init.InitUtil.savePublic;
import static com.google.gerrit.pgm.init.InitUtil.saveSecure;
import static com.google.gerrit.pgm.init.InitUtil.version;

import com.google.gerrit.pgm.BaseInit;
import com.google.gerrit.pgm.util.ConsoleUI;
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.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;

  @Inject
  public SitePathInitializer(final Injector injector, final ConsoleUI ui,
      final InitFlags flags, final SitePaths site) {
    this.ui = ui;
    this.flags = flags;
    this.site = site;
    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();
    }

    savePublic(flags.cfg);
    saveSecure(flags.sec);

    extract(site.gerrit_sh, BaseInit.class, "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 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>() {});
  }
}
