// Copyright (C) 2017 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.project;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import com.google.gerrit.entities.BooleanProjectConfig;
import com.google.gerrit.extensions.api.projects.ConfigInfo;
import com.google.gerrit.extensions.api.projects.ConfigInfo.InheritedBooleanInfo;
import com.google.gerrit.extensions.api.projects.ConfigInput;
import com.google.gerrit.extensions.client.InheritableBoolean;
import java.util.Arrays;
import java.util.HashSet;

/** Provides transformations to get and set BooleanProjectConfigs from the API. */
public class BooleanProjectConfigTransformations {

  private static ImmutableMap<BooleanProjectConfig, Mapper> MAPPER =
      ImmutableMap.<BooleanProjectConfig, Mapper>builder()
          .put(
              BooleanProjectConfig.USE_CONTRIBUTOR_AGREEMENTS,
              new Mapper(i -> i.useContributorAgreements, (i, v) -> i.useContributorAgreements = v))
          .put(
              BooleanProjectConfig.USE_SIGNED_OFF_BY,
              new Mapper(i -> i.useSignedOffBy, (i, v) -> i.useSignedOffBy = v))
          .put(
              BooleanProjectConfig.USE_CONTENT_MERGE,
              new Mapper(i -> i.useContentMerge, (i, v) -> i.useContentMerge = v))
          .put(
              BooleanProjectConfig.REQUIRE_CHANGE_ID,
              new Mapper(i -> i.requireChangeId, (i, v) -> i.requireChangeId = v))
          .put(
              BooleanProjectConfig.CREATE_NEW_CHANGE_FOR_ALL_NOT_IN_TARGET,
              new Mapper(
                  i -> i.createNewChangeForAllNotInTarget,
                  (i, v) -> i.createNewChangeForAllNotInTarget = v))
          .put(
              BooleanProjectConfig.ENABLE_SIGNED_PUSH,
              new Mapper(i -> i.enableSignedPush, (i, v) -> i.enableSignedPush = v))
          .put(
              BooleanProjectConfig.REQUIRE_SIGNED_PUSH,
              new Mapper(i -> i.requireSignedPush, (i, v) -> i.requireSignedPush = v))
          .put(
              BooleanProjectConfig.REJECT_IMPLICIT_MERGES,
              new Mapper(i -> i.rejectImplicitMerges, (i, v) -> i.rejectImplicitMerges = v))
          .put(
              BooleanProjectConfig.PRIVATE_BY_DEFAULT,
              new Mapper(i -> i.privateByDefault, (i, v) -> i.privateByDefault = v))
          .put(
              BooleanProjectConfig.ENABLE_REVIEWER_BY_EMAIL,
              new Mapper(i -> i.enableReviewerByEmail, (i, v) -> i.enableReviewerByEmail = v))
          .put(
              BooleanProjectConfig.MATCH_AUTHOR_TO_COMMITTER_DATE,
              new Mapper(
                  i -> i.matchAuthorToCommitterDate, (i, v) -> i.matchAuthorToCommitterDate = v))
          .put(
              BooleanProjectConfig.REJECT_EMPTY_COMMIT,
              new Mapper(i -> i.rejectEmptyCommit, (i, v) -> i.rejectEmptyCommit = v))
          .put(
              BooleanProjectConfig.WORK_IN_PROGRESS_BY_DEFAULT,
              new Mapper(i -> i.workInProgressByDefault, (i, v) -> i.workInProgressByDefault = v))
          .build();

  static {
    // Verify that each BooleanProjectConfig has to/from API mappers in
    // BooleanProjectConfigTransformations
    if (!Sets.symmetricDifference(
            MAPPER.keySet(), new HashSet<>(Arrays.asList(BooleanProjectConfig.values())))
        .isEmpty()) {
      throw new IllegalStateException(
          "All values of BooleanProjectConfig must have transformations associated with them");
    }
  }

  @FunctionalInterface
  private interface ToApi {
    void apply(ConfigInfo info, InheritedBooleanInfo val);
  }

  @FunctionalInterface
  private interface FromApi {
    InheritableBoolean apply(ConfigInput input);
  }

  public static void set(BooleanProjectConfig cfg, ConfigInfo info, InheritedBooleanInfo val) {
    MAPPER.get(cfg).set(info, val);
  }

  public static InheritableBoolean get(BooleanProjectConfig cfg, ConfigInput input) {
    return MAPPER.get(cfg).get(input);
  }

  private static class Mapper {
    private final FromApi fromApi;
    private final ToApi toApi;

    private Mapper(FromApi fromApi, ToApi toApi) {
      this.fromApi = fromApi;
      this.toApi = toApi;
    }

    public void set(ConfigInfo info, InheritedBooleanInfo val) {
      toApi.apply(info, val);
    }

    public InheritableBoolean get(ConfigInput input) {
      return fromApi.apply(input);
    }
  }
}
