// 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.GroupInfo;
import com.google.gerrit.extensions.common.ProjectInfo;
import com.google.gerrit.extensions.common.SshKeyInfo;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;

import org.eclipse.jgit.errors.ConfigInvalidException;

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, ConfigInvalidException;

  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;
    }
  }
}
