// Copyright (C) 2008 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.reviewdb;

import com.google.gwtorm.client.Column;
import com.google.gwtorm.client.IntKey;

import java.sql.Timestamp;

/** An SSH key approved for use by an {@link Account}. */
public final class AccountSshKey {
  public static class Id extends IntKey<Account.Id> {
    private static final long serialVersionUID = 1L;

    @Column
    protected Account.Id accountId;

    @Column
    protected int seq;

    protected Id() {
      accountId = new Account.Id();
    }

    public Id(final Account.Id a, final int s) {
      accountId = a;
      seq = s;
    }

    @Override
    public Account.Id getParentKey() {
      return accountId;
    }

    @Override
    public int get() {
      return seq;
    }

    @Override
    protected void set(int newValue) {
      seq = newValue;
    }
  }

  @Column(name = Column.NONE)
  protected AccountSshKey.Id id;

  @Column(length = Integer.MAX_VALUE)
  protected String sshPublicKey;

  @Column
  protected Timestamp storedOn;

  @Column
  protected boolean valid;

  @Column(notNull = false)
  protected Timestamp lastUsedOn;

  protected AccountSshKey() {
  }

  public AccountSshKey(final AccountSshKey.Id i, final String pub) {
    id = i;
    sshPublicKey = pub;
    storedOn = new Timestamp(System.currentTimeMillis());
    valid = true; // We can assume it is fine.
  }

  public Account.Id getAccount() {
    return id.accountId;
  }

  public AccountSshKey.Id getKey() {
    return id;
  }

  public String getSshPublicKey() {
    return sshPublicKey;
  }

  public String getAlgorithm() {
    final String s = getSshPublicKey();
    if (s == null || s.length() == 0) {
      return "none";
    }

    final String[] parts = s.split(" ");
    if (parts.length < 1) {
      return "none";
    }
    return parts[0];
  }

  public String getEncodedKey() {
    final String s = getSshPublicKey();
    if (s == null || s.length() == 0) {
      return null;
    }

    final String[] parts = s.split(" ");
    if (parts.length < 2) {
      return null;
    }
    return parts[1];
  }

  public String getComment() {
    final String s = getSshPublicKey();
    if (s == null || s.length() == 0) {
      return "";
    }

    final String[] parts = s.split(" ", 3);
    if (parts.length < 3) {
      return "";
    }
    return parts[2];
  }

  public Timestamp getStoredOn() {
    return storedOn;
  }

  public boolean isValid() {
    return valid;
  }

  public void setInvalid() {
    valid = false;
  }

  public Timestamp getLastUsedOn() {
    return lastUsedOn;
  }

  public void setLastUsedOn() {
    lastUsedOn = new Timestamp(System.currentTimeMillis());
  }
}
