// Copyright (C) 2010 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.schema;

import static com.google.gerrit.common.data.Permission.CREATE;
import static com.google.gerrit.common.data.Permission.FORGE_AUTHOR;
import static com.google.gerrit.common.data.Permission.FORGE_COMMITTER;
import static com.google.gerrit.common.data.Permission.FORGE_SERVER;
import static com.google.gerrit.common.data.Permission.LABEL;
import static com.google.gerrit.common.data.Permission.OWNER;
import static com.google.gerrit.common.data.Permission.PUSH;
import static com.google.gerrit.common.data.Permission.PUSH_MERGE;
import static com.google.gerrit.common.data.Permission.PUSH_TAG;
import static com.google.gerrit.common.data.Permission.READ;
import static com.google.gerrit.common.data.Permission.SUBMIT;

import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.common.data.LabelType;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.common.data.PermissionRule;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.client.PatchSetApproval.LabelId;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.Project.InheritableBoolean;
import com.google.gerrit.reviewdb.client.SystemConfig;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.account.GroupUUID;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.schema.Schema_77.LegacyLabelTypes;
import com.google.gwtorm.jdbc.JdbcSchema;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;

import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;

import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class Schema_53 extends SchemaVersion {
  private final GitRepositoryManager mgr;
  private final PersonIdent serverUser;

  private SystemConfig systemConfig;
  private Map<AccountGroup.Id, GroupReference> groupMap;
  private LegacyLabelTypes labelTypes;
  private GroupReference projectOwners;

  private Map<Project.NameKey, Project.NameKey> parentsByProject;
  private Map<Project.NameKey, List<OldRefRight>> rightsByProject;

  private final String OLD_SUBMIT = "SUBM";
  private final String OLD_READ = "READ";
  private final String OLD_OWN = "OWN";
  private final String OLD_PUSH_TAG = "pTAG";
  private final String OLD_PUSH_HEAD = "pHD";
  private final String OLD_FORGE_IDENTITY = "FORG";

  @Inject
  Schema_53(Provider<Schema_52> prior, GitRepositoryManager mgr,
      @GerritPersonIdent PersonIdent serverUser) {
    super(prior);
    this.mgr = mgr;
    this.serverUser = serverUser;
  }

  @Override
  protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException,
      SQLException {
    systemConfig = db.systemConfig().get(new SystemConfig.Key());
    labelTypes = Schema_77.getLegacyTypes(db);

    assignGroupUUIDs(db);
    readOldRefRights(db);
    readProjectParents(db);
    exportProjectConfig(db);

    deleteActionCategories(db);
  }

  private void deleteActionCategories(ReviewDb db) throws OrmException {
    try {
      Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
      try {
        stmt.executeUpdate(
            "DELETE FROM approval_categories WHERE position < 0");
      } finally {
        stmt.close();
      }
    } catch (SQLException e) {
      throw new OrmException(e);
    }
  }

  private void assignGroupUUIDs(ReviewDb db) throws OrmException {
    groupMap = new HashMap<AccountGroup.Id, GroupReference>();
    List<AccountGroup> groups = db.accountGroups().all().toList();
    for (AccountGroup g : groups) {
      if (g.getId().equals(systemConfig.ownerGroupId)) {
        g.setGroupUUID(SystemGroupBackend.PROJECT_OWNERS);
        projectOwners = GroupReference.forGroup(g);

      } else if (g.getId().equals(systemConfig.anonymousGroupId)) {
        g.setGroupUUID(SystemGroupBackend.ANONYMOUS_USERS);

      } else if (g.getId().equals(systemConfig.registeredGroupId)) {
        g.setGroupUUID(SystemGroupBackend.REGISTERED_USERS);

      } else {
        g.setGroupUUID(GroupUUID.make(g.getName(), serverUser));
      }
      groupMap.put(g.getId(), GroupReference.forGroup(g));
    }
    db.accountGroups().update(groups);

    systemConfig.adminGroupUUID = toUUID(systemConfig.adminGroupId);
    systemConfig.batchUsersGroupUUID = toUUID(systemConfig.batchUsersGroupId);
    db.systemConfig().update(Collections.singleton(systemConfig));
  }

  private AccountGroup.UUID toUUID(AccountGroup.Id id) {
    return groupMap.get(id).getUUID();
  }

  private void exportProjectConfig(ReviewDb db) throws OrmException,
      SQLException {
    Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
    ResultSet rs = stmt.executeQuery("SELECT * FROM projects ORDER BY name");
    while (rs.next()) {
      final String name = rs.getString("name");
      final Project.NameKey nameKey = new Project.NameKey(name);

      Repository git;
      try {
        git = mgr.openRepository(nameKey);
      } catch (RepositoryNotFoundException notFound) {
        // A repository may be missing if this project existed only to store
        // inheritable permissions. For example 'All-Projects'.
        try {
          git = mgr.createRepository(nameKey);
        } catch (IOException err) {
          throw new OrmException("Cannot create repository " + name, err);
        }
      } catch (IOException e) {
        throw new OrmException(e);
      }
      try {
        MetaDataUpdate md =
            new MetaDataUpdate(GitReferenceUpdated.DISABLED, nameKey, git);
        md.getCommitBuilder().setAuthor(serverUser);
        md.getCommitBuilder().setCommitter(serverUser);

        ProjectConfig config = ProjectConfig.read(md);
        loadProject(rs, config.getProject());
        config.getAccessSections().clear();
        convertRights(config);

        // Grant out read on the config branch by default.
        //
        if (config.getProject().getNameKey().equals(systemConfig.wildProjectName)) {
          AccessSection meta = config.getAccessSection(RefNames.REFS_CONFIG, true);
          Permission read = meta.getPermission(READ, true);
          read.getRule(config.resolve(projectOwners), true);
        }

        md.setMessage("Import project configuration from SQL\n");
        config.commit(md);
      } catch (ConfigInvalidException err) {
        throw new OrmException("Cannot read project " + name, err);
      } catch (IOException err) {
        throw new OrmException("Cannot export project " + name, err);
      } finally {
        git.close();
      }
    }
    rs.close();
    stmt.close();
  }

  private void loadProject(ResultSet rs, Project project) throws SQLException,
      OrmException {
    project.setDescription(rs.getString("description"));
    project.setUseContributorAgreements(asInheritableBoolean(rs, "use_contributor_agreements"));

    switch (rs.getString("submit_type").charAt(0)) {
      case 'F':
        project.setSubmitType(Project.SubmitType.FAST_FORWARD_ONLY);
        break;
      case 'M':
        project.setSubmitType(Project.SubmitType.MERGE_IF_NECESSARY);
        break;
      case 'A':
        project.setSubmitType(Project.SubmitType.MERGE_ALWAYS);
        break;
      case 'C':
        project.setSubmitType(Project.SubmitType.CHERRY_PICK);
        break;
      default:
        throw new OrmException("Unsupported submit_type="
            + rs.getString("submit_type") + " on project " + project.getName());
    }

    project.setUseSignedOffBy(asInheritableBoolean(rs, "use_signed_off_by"));
    project.setRequireChangeID(asInheritableBoolean(rs, "require_change_id"));
    project.setUseContentMerge(asInheritableBoolean(rs, "use_content_merge"));
    project.setParentName(rs.getString("parent_name"));
  }

  private static InheritableBoolean asInheritableBoolean(ResultSet rs, String col)
      throws SQLException {
    return "Y".equals(rs.getString(col))
        ? Project.InheritableBoolean.TRUE
        : Project.InheritableBoolean.INHERIT;
  }

  private void readOldRefRights(ReviewDb db) throws SQLException {
    rightsByProject = new HashMap<Project.NameKey, List<OldRefRight>>();

    Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
    ResultSet rs = stmt.executeQuery("SELECT * FROM ref_rights");
    while (rs.next()) {
      OldRefRight right = new OldRefRight(rs);
      if (right.group == null || right.category == null) {
        continue;
      }

      List<OldRefRight> list;

      list = rightsByProject.get(right.project);
      if (list == null) {
        list = new ArrayList<OldRefRight>();
        rightsByProject.put(right.project, list);
      }
      list.add(right);
    }
    rs.close();
    stmt.close();
  }

  private void readProjectParents(ReviewDb db) throws SQLException {
    parentsByProject = new HashMap<Project.NameKey, Project.NameKey>();
    Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
    ResultSet rs = stmt.executeQuery("SELECT * FROM projects");
    while (rs.next()) {
      String name = rs.getString("name");
      String parent_name = rs.getString("parent_name");
      if (parent_name == null) {
        parent_name = systemConfig.wildProjectName.get();
      }
      parentsByProject.put(new Project.NameKey(name), //
          new Project.NameKey(parent_name));
    }
    rs.close();
    stmt.close();
  }

  private void convertRights(ProjectConfig config) {
    List<OldRefRight> myRights =
        rightsByProject.get(config.getProject().getNameKey());
    if (myRights == null) {
      return;
    }

    for (OldRefRight old : myRights) {
      AccessSection section = config.getAccessSection(old.ref_pattern, true);
      GroupReference group = config.resolve(old.group);

      if (OLD_SUBMIT.equals(old.category)) {
        PermissionRule submit = rule(group);
        if (old.max_value <= 0) {
          submit.setDeny();
        }
        add(section, SUBMIT, old.exclusive, submit);

      } else if (OLD_READ.equals(old.category)) {
        if (old.exclusive) {
          section.getPermission(READ, true).setExclusiveGroup(true);
          newChangePermission(config, old.ref_pattern).setExclusiveGroup(true);
        }

        PermissionRule read = rule(group);
        if (old.max_value <= 0) {
          read.setDeny();
        }
        add(section, READ, old.exclusive, read);

        if (3 <= old.max_value) {
          newMergePermission(config, old.ref_pattern).add(rule(group));
        } else if (3 <= inheritedMax(config, old)) {
          newMergePermission(config, old.ref_pattern).add(deny(group));
        }

        if (2 <= old.max_value) {
          newChangePermission(config, old.ref_pattern).add(rule(group));
        } else if (2 <= inheritedMax(config, old)) {
          newChangePermission(config, old.ref_pattern).add(deny(group));
        }

      } else if (OLD_OWN.equals(old.category)) {
        add(section, OWNER, false, rule(group));

      } else if (OLD_PUSH_TAG.equals(old.category)) {
        PermissionRule push = rule(group);
        if (old.max_value <= 0) {
          push.setDeny();
        }
        add(section, PUSH_TAG, old.exclusive, push);

      } else if (OLD_PUSH_HEAD.equals(old.category)) {
        if (old.exclusive) {
          section.getPermission(PUSH, true).setExclusiveGroup(true);
          section.getPermission(CREATE, true).setExclusiveGroup(true);
        }

        PermissionRule push = rule(group);
        if (old.max_value <= 0) {
          push.setDeny();
        }
        push.setForce(3 <= old.max_value);
        add(section, PUSH, old.exclusive, push);

        if (2 <= old.max_value) {
          add(section, CREATE, old.exclusive, rule(group));
        } else if (2 <= inheritedMax(config, old)) {
          add(section, CREATE, old.exclusive, deny(group));
        }

      } else if (OLD_FORGE_IDENTITY.equals(old.category)) {
        if (old.exclusive) {
          section.getPermission(FORGE_AUTHOR, true).setExclusiveGroup(true);
          section.getPermission(FORGE_COMMITTER, true).setExclusiveGroup(true);
          section.getPermission(FORGE_SERVER, true).setExclusiveGroup(true);
        }

        if (1 <= old.max_value) {
          add(section, FORGE_AUTHOR, old.exclusive, rule(group));
        }

        if (2 <= old.max_value) {
          add(section, FORGE_COMMITTER, old.exclusive, rule(group));
        } else if (2 <= inheritedMax(config, old)) {
          add(section, FORGE_COMMITTER, old.exclusive, deny(group));
        }

        if (3 <= old.max_value) {
          add(section, FORGE_SERVER, old.exclusive, rule(group));
        } else if (3 <= inheritedMax(config, old)) { add(section, FORGE_SERVER, old.exclusive, deny(group));
        }

      } else {
        PermissionRule rule = rule(group);
        rule.setRange(old.min_value, old.max_value);
        if (old.min_value == 0 && old.max_value == 0) {
          rule.setDeny();
        }
        LabelType type = labelTypes.byLabel(new LabelId(old.category));
        String name = type != null ? type.getName() : old.category;
        add(section, LABEL + name, old.exclusive, rule);
      }
    }
  }

  private static Permission newChangePermission(ProjectConfig config,
      String name) {
    if (name.startsWith(AccessSection.REGEX_PREFIX)) {
      name = AccessSection.REGEX_PREFIX
          + "refs/for/"
          + name.substring(AccessSection.REGEX_PREFIX.length());
    } else {
      name = "refs/for/" + name;
    }
    return config.getAccessSection(name, true).getPermission(PUSH, true);
  }

  private static Permission newMergePermission(ProjectConfig config,
      String name) {
    if (name.startsWith(AccessSection.REGEX_PREFIX)) {
      name = AccessSection.REGEX_PREFIX
          + "refs/for/"
          + name.substring(AccessSection.REGEX_PREFIX.length());
    } else {
      name = "refs/for/" + name;
    }
    return config.getAccessSection(name, true).getPermission(PUSH_MERGE, true);
  }

  private static PermissionRule rule(GroupReference group) {
    return new PermissionRule(group);
  }

  private static PermissionRule deny(GroupReference group) {
    PermissionRule rule = rule(group);
    rule.setDeny();
    return rule;
  }

  private int inheritedMax(ProjectConfig config, OldRefRight old) {
    int max = 0;

    String ref = old.ref_pattern;
    String category = old.category;
    AccountGroup.UUID group = old.group.getUUID();

    Project.NameKey project = config.getProject().getParent();
    if (project == null) {
      project = systemConfig.wildProjectName;
    }
    do {
      List<OldRefRight> rights = rightsByProject.get(project);
      if (rights != null) {
        for (OldRefRight r : rights) {
          if (r.ref_pattern.equals(ref) //
              && r.group.getUUID().equals(group) //
              && r.category.equals(category)) {
            max = Math.max(max, r.max_value);
            break;
          }
        }
      }
      project = parentsByProject.get(project);
    } while (!project.equals(systemConfig.wildProjectName));

    return max;
  }

  private static void add(AccessSection section, String name,
      boolean exclusive, PermissionRule rule) {
    Permission p = section.getPermission(name, true);
    if (exclusive) {
      p.setExclusiveGroup(true);
    }
    p.add(rule);
  }

  private class OldRefRight {
    final int min_value;
    final int max_value;
    final String ref_pattern;
    final boolean exclusive;
    final GroupReference group;
    final String category;
    final Project.NameKey project;

    OldRefRight(ResultSet rs) throws SQLException {
      min_value = rs.getInt("min_value");
      max_value = rs.getInt("max_value");
      project = new Project.NameKey(rs.getString("project_name"));

      String r = rs.getString("ref_pattern");
      exclusive = r.startsWith("-");
      if (exclusive) {
        r = r.substring(1);
      }
      ref_pattern = r;

      category = rs.getString("category_id");
      group = groupMap.get(new AccountGroup.Id(rs.getInt("group_id")));
    }
  }
}
