// Copyright (C) 2011 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.util;

import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.SubmoduleSubscription;

import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashSet;
import java.util.Set;

/**
 * It parses from a configuration file submodule sections.
 * <p>
 * Example of submodule sections:
 *
 * <pre>
 * [submodule "project-a"]
 *     url = http://localhost/a
 *     path = a
 *     branch = .
 *
 * [submodule "project-b"]
 *     url = http://localhost/b
 *     path = b
 *     branch = refs/heads/test
 * </pre>
 */
public class SubmoduleSectionParser {

  private final Config bbc;
  private final String canonicalWebUrl;
  private final Branch.NameKey superProjectBranch;

  public SubmoduleSectionParser(Config bbc,
      String canonicalWebUrl,
      Branch.NameKey superProjectBranch) {
    this.bbc = bbc;
    this.canonicalWebUrl = canonicalWebUrl;
    this.superProjectBranch = superProjectBranch;
  }

  public Set<SubmoduleSubscription> parseAllSections() {
    Set<SubmoduleSubscription> parsedSubscriptions = new HashSet<>();
    for (final String id : bbc.getSubsections("submodule")) {
      final SubmoduleSubscription subscription = parse(id);
      if (subscription != null) {
        parsedSubscriptions.add(subscription);
      }
    }
    return parsedSubscriptions;
  }

  private SubmoduleSubscription parse(final String id) {
    final String url = bbc.getString("submodule", id, "url");
    final String path = bbc.getString("submodule", id, "path");
    String branch = bbc.getString("submodule", id, "branch");

    try {
      if (url != null && url.length() > 0 && path != null && path.length() > 0
          && branch != null && branch.length() > 0) {
        // All required fields filled.
        String project;

        if (branch.equals(".")) {
          branch = superProjectBranch.get();
        }

        // relative URL
        if (url.startsWith("../")) {
          // prefix with a slash for easier relative path walks
          project = '/' + superProjectBranch.getParentKey().get();
          String hostPart = url;
          while (hostPart.startsWith("../")) {
            int lastSlash = project.lastIndexOf('/');
            if (lastSlash < 0) {
              // too many levels up, ignore for now
              return null;
            }
            project = project.substring(0, lastSlash);
            hostPart = hostPart.substring(3);
          }
          project = project + "/" + hostPart;

          // remove leading '/'
          project = project.substring(1);
        } else {
          // It is actually an URI. It could be ssh://localhost/project-a.
          URI targetServerURI = new URI(url);
          URI thisServerURI = new URI(canonicalWebUrl);
          String thisHost = thisServerURI.getHost();
          String targetHost = targetServerURI.getHost();
          if (thisHost == null || targetHost == null ||
              !targetHost.equalsIgnoreCase(thisHost)) {
            return null;
          }
          String p1 = targetServerURI.getPath();
          String p2 = thisServerURI.getPath();
          if (!p1.startsWith(p2)) {
            // When we are running the server at
            // http://server/my-gerrit/ but the subscription is for
            // http://server/other-teams-gerrit/
            return null;
          }
          // skip common part
          project = p1.substring(p2.length());
        }

        while (project.startsWith("/")) {
          project = project.substring(1);
        }

        if (project.endsWith(Constants.DOT_GIT_EXT)) {
          project = project.substring(0, //
              project.length() - Constants.DOT_GIT_EXT.length());
        }
        Project.NameKey projectKey = new Project.NameKey(project);
        return new SubmoduleSubscription(
            superProjectBranch,
            new Branch.NameKey(projectKey, branch),
            path);
      }
    } catch (URISyntaxException e) {
      // Error in url syntax (in fact it is uri syntax)
    }
    return null;
  }
}
