// Copyright (C) 2014 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.gitblit.auth;

import com.gitblit.Constants.AccessPermission;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.StringUtils;
import com.google.gerrit.reviewdb.client.Project.NameKey;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.server.project.ProjectControl.Factory;
import java.util.HashSet;
import java.util.Set;

public class GerritToGitBlitUserModel extends UserModel {
  public static final String ANONYMOUS_USER = "$anonymous";
  public static final char[] ANONYMOUS_PASSWORD = ANONYMOUS_USER.toCharArray();

  private static final long serialVersionUID = 1L;

  // field names are reflectively mapped in EditUser page
  public String username;
  public String password;
  public String cookie;
  public String displayName;
  public String emailAddress;
  public boolean canAdmin;
  public boolean excludeFromFederation;
  public final Set<String> repositories = new HashSet<>();
  public final Set<TeamModel> teams = new HashSet<>();

  private final transient ProjectControl.Factory projectControlFactory;

  // non-persisted fields
  public boolean isAuthenticated;

  public GerritToGitBlitUserModel(String username) {
    this(username, null);
  }

  public GerritToGitBlitUserModel(
      String username, final ProjectControl.Factory projectControlFactory) {
    super(username);
    this.username = username;
    this.isAuthenticated = true;
    this.projectControlFactory = projectControlFactory;
  }

  public GerritToGitBlitUserModel(final ProjectControl.Factory projectControlFactory) {
    super(ANONYMOUS_USER);
    this.projectControlFactory = projectControlFactory;
  }

  @Deprecated
  public boolean canAccessRepository(String repositoryName) {
    boolean result = false;

    try {
      ProjectControl control = projectControlFactory.controlFor(new NameKey(repositoryName));
      result = control != null;
    } catch (NoSuchProjectException e) {
      result = false;
    }

    return result;
  }

  @Override
  protected boolean canAccess(
      RepositoryModel repository,
      AccessRestrictionType ifRestriction,
      AccessPermission requirePermission) {
    boolean result = false;

    try {
      ProjectControl control =
          projectControlFactory.controlFor(new NameKey(getRepositoryName(repository.name)));

      if (control == null) {
        return false;
      }

      switch (ifRestriction) {
        case VIEW:
          return !control.isHidden();
        case CLONE:
          return control.canRunUploadPack();
        case PUSH:
          return control.canRunReceivePack();
        case NONE:
        default:
          return true;
      }
    } catch (NoSuchProjectException e) {
      result = false;
    }

    return result;
  }

  public String getRepositoryName(String name) {
    if (name.endsWith(".git")) {
      name = name.substring(0, name.length() - 4);
    }
    return name;
  }

  @Override
  public boolean hasRepositoryPermission(String name) {
    boolean result = false;

    try {
      name = getRepositoryName(name);
      ProjectControl control = projectControlFactory.controlFor(new NameKey(name));
      result = control != null && !control.isHidden();
    } catch (NoSuchProjectException e) {
      result = false;
    }

    return result;
  }

  public boolean hasTeamAccess(String repositoryName) {
    for (TeamModel team : teams) {
      if (team.hasRepositoryPermission(repositoryName)) {
        return true;
      }
    }
    return false;
  }

  public boolean hasRepository(String name) {
    return repositories.contains(name.toLowerCase());
  }

  public void addRepository(String name) {
    repositories.add(name.toLowerCase());
  }

  public void removeRepository(String name) {
    repositories.remove(name.toLowerCase());
  }

  @Override
  public boolean isTeamMember(String teamname) {
    for (TeamModel team : teams) {
      if (team.name.equalsIgnoreCase(teamname)) {
        return true;
      }
    }
    return false;
  }

  @Override
  public TeamModel getTeam(String teamname) {
    if (teams == null) {
      return null;
    }
    for (TeamModel team : teams) {
      if (team.name.equalsIgnoreCase(teamname)) {
        return team;
      }
    }
    return null;
  }

  @Override
  public String getName() {
    return username;
  }

  @Override
  public String getDisplayName() {
    if (StringUtils.isEmpty(displayName)) {
      return username;
    }
    return displayName;
  }

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

  @Override
  public int compareTo(UserModel o) {
    return username.compareTo(o.username);
  }

  public static UserModel getAnonymous(Factory projectControl) {
    return new GerritToGitBlitUserModel(ANONYMOUS_USER, projectControl);
  }
}
