// Copyright (C) 2015 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.googlesource.gerrit.plugins.importer;

import com.google.common.base.Objects;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.extensions.common.ProjectInfo;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.server.account.GetSshKeys.SshKeyInfo;
import com.google.gerrit.server.group.GroupJson.GroupInfo;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;

import java.io.IOException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

interface GerritApi {

  class Factory {
    private final LocalApi localApi;

    @Inject
    Factory(LocalApi localApi) {
      this.localApi = localApi;
    }

    GerritApi create(String url, String user, String pass) {
      if (url == null) {
        return localApi;
      } else {
        return new RemoteApi(url, user, pass);
      }
    }
  }

  public ProjectInfo getProject(String projectName) throws BadRequestException,
      IOException;

  public List<ChangeInfo> queryChanges(String projectName, int start, int limit)
      throws BadRequestException, IOException;

  public GroupInfo getGroup(String groupName) throws BadRequestException,
      IOException, OrmException;

  /**
   * Retrieves inline comments of a patch set.
   *
   * @param changeId numeric change ID
   * @param rev the revision
   * @return Iterable that provides the inline comments, or {@code null} if the
   *         revision does not exist
   * @throws IOException thrown if sending the request fails
   * @throws BadRequestException thrown if the response is neither
   *         {@code 200 OK} nor {@code 404 Not Found}
   */
  public Iterable<CommentInfo> getComments(int changeId, String rev)
      throws BadRequestException, IOException, OrmException;

  public List<SshKeyInfo> getSshKeys(String userId) throws BadRequestException,
      IOException, OrmException;

  public Version getVersion() throws BadRequestException, IOException;

  class Version implements Comparable<Version> {
    final String formatted;
    final Integer major;
    final Integer minor;
    final Integer patch;
    final String qualifier;

    Version(String formatted) {
      this.formatted = formatted;

      Matcher m = Pattern.compile("(\\d+)\\.(\\d+)(\\.(\\d+))?(-(.+))?")
          .matcher(formatted);
      if (m.matches()) {
        this.major = Integer.parseInt(m.group(1));
        this.minor = Integer.parseInt(m.group(2));
        this.patch = m.group(3) != null ? Integer.parseInt(m.group(4)) : null;
        this.qualifier = m.group(5) != null ? m.group(6) : null;
      } else {
        this.major = null;
        this.minor = null;
        this.patch = null;
        this.qualifier = null;
      }
    }

    @Override
    public int compareTo(Version o) {
      if (major == null || o.major == null) {
        // either of the compared version is not valid
        return -1;
      }
      if (major == o.major) {
        if (Objects.equal(minor, o.minor)) {
          if (Objects.equal(patch, o.patch)) {
            return 0;
          }
          if (o.patch == null) {
            return 1;
          }
          if (patch == null) {
            return -1;
          }
          return patch - o.patch;
        } else {
          if (o.minor == null) {
            return 1;
          }
          if (minor == null) {
            return -1;
          }
          return minor - o.minor;
        }
      } else {
        return major - o.major;
      }
    }

    @Override
    public String toString() {
      return formatted;
    }
  }
}
