// Copyright 2020 The Bazel Authors. All rights reserved.
//
// 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.devtools.build.lib.authandtls;

import static com.google.common.base.Predicates.not;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.auto.value.AutoValue;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.authandtls.Netrc.Credential;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;

/**
 * A parser used to parse .netrc content.
 *
 * @see <a href="https://man.cx/netrc(4)">netrc − file for ftp remote login data</a>
 * @see <a
 *     href="https://github.com/bazelbuild/bazel/blob/master/tools/build_defs/repo/utils.bzl#L203-L204">Starlark
 *     netrc parser</a>
 */
public class NetrcParser {
  private static final String MACHINE = "machine";
  private static final String MACDEF = "macdef";
  private static final String DEFAULT = "default";
  private static final String LOGIN = "login";
  private static final String PASSWORD = "password";
  private static final String ACCOUNT = "account";

  interface Token {}

  @AutoValue
  abstract static class ItemToken implements Token {
    public static ItemToken create(String item) {
      return new AutoValue_NetrcParser_ItemToken(item);
    }

    abstract String item();
  }

  @AutoValue
  abstract static class NewlineToken implements Token {
    public static NewlineToken create() {
      return new AutoValue_NetrcParser_NewlineToken();
    }
  }

  @AutoValue
  abstract static class CommentToken implements Token {
    public static CommentToken create() {
      return new AutoValue_NetrcParser_CommentToken();
    }
  }

  private static class TokenStream implements Closeable {
    private final BufferedReader bufferedReader;
    private final Queue<Token> tokens = new ArrayDeque<>();

    TokenStream(InputStream inputStream) throws IOException {
      bufferedReader = new BufferedReader(new InputStreamReader(inputStream, UTF_8));
      processLine();
    }

    @Override
    public void close() throws IOException {
      bufferedReader.close();
    }

    private void processLine() throws IOException {
      String line = bufferedReader.readLine();
      if (line == null) {
        return;
      }

      // Comments start with #
      if (line.startsWith("#")) {
        tokens.add(CommentToken.create());
      } else {
        Arrays.stream(line.split("\\s+"))
            .filter(not(Strings::isNullOrEmpty))
            .map(ItemToken::create)
            .forEach(tokens::add);
      }

      tokens.add(NewlineToken.create());
    }

    public boolean hasNext() {
      return !tokens.isEmpty();
    }

    public Token next() throws IOException {
      Token token = tokens.poll();
      if (tokens.isEmpty()) {
        processLine();
      }
      return token;
    }

    public Token peek() {
      return tokens.peek();
    }
  }

  private NetrcParser() {}

  public static Netrc parseAndClose(InputStream inputStream) throws IOException {
    try (TokenStream tokenStream = new TokenStream(inputStream)) {
      return parse(tokenStream);
    }
  }

  private static Netrc parse(TokenStream tokenStream) throws IOException {
    Credential defaultCredential = null;
    Map<String, Credential> credentialMap = new HashMap<>();

    boolean done = false;
    while (!done && tokenStream.hasNext()) {
      Token token = tokenStream.next();
      if (token instanceof ItemToken) {
        String item = ((ItemToken) token).item();
        switch (item) {
          case MACHINE:
            String machine = nextItem(tokenStream);
            Credential credential = parseCredentialForMachine(tokenStream, machine);
            credentialMap.put(machine, credential);
            break;
          case MACDEF:
            skipMacdef(tokenStream);
            break;
          case DEFAULT:
            defaultCredential = parseCredentialForMachine(tokenStream, DEFAULT);
            // There can be only one default token, and it must be after all machine tokens.
            done = true;
            break;
          default:
            throw new IOException(
                String.format(
                    "Unexpected token: %s (expecting %s, %s or %s)",
                    item, MACHINE, MACDEF, DEFAULT));
        }
      }
    }

    return Netrc.create(defaultCredential, ImmutableMap.copyOf(credentialMap));
  }

  private static String nextItem(TokenStream tokenStream) throws IOException {
    while (tokenStream.hasNext()) {
      Token token = tokenStream.next();
      if (token instanceof ItemToken) {
        return ((ItemToken) token).item();
      }
    }

    throw new IOException("Unexpected EOF");
  }

  /** Parse credentials for a given machine from token stream. */
  private static Credential parseCredentialForMachine(TokenStream tokenStream, String machine)
      throws IOException {
    Credential.Builder builder = Credential.builder(machine);

    boolean done = false;
    while (!done && tokenStream.hasNext()) {
      // Peek rather than taking next token since we probably won't process it
      Token token = tokenStream.peek();
      if (token instanceof ItemToken) {
        String item = ((ItemToken) token).item();
        switch (item) {
          case LOGIN:
            tokenStream.next();
            builder.setLogin(nextItem(tokenStream));
            break;
          case PASSWORD:
            tokenStream.next();
            builder.setPassword(nextItem(tokenStream));
            break;
          case ACCOUNT:
            tokenStream.next();
            builder.setAccount(nextItem(tokenStream));
            break;
          case MACHINE:
          case MACDEF:
          case DEFAULT:
            done = true;
            break;
          default:
            throw new IOException(
                String.format(
                    "Unexpected item: %s (expecting %s, %s, %s, %s, %s or %s)",
                    item, LOGIN, PASSWORD, ACCOUNT, MACHINE, MACDEF, DEFAULT));
        }
      } else {
        tokenStream.next();
      }
    }

    return builder.build();
  }

  /** Skip macdef section since we don't need that data currently. */
  private static void skipMacdef(TokenStream tokenStream) throws IOException {
    int numNewlines = 0;
    while (tokenStream.hasNext()) {
      Token token = tokenStream.next();
      if (token instanceof NewlineToken) {
        ++numNewlines;
      } else {
        numNewlines = 0;
      }
      if (numNewlines >= 2) {
        break;
      }
    }
  }
}
