// 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.repositoryuse;

import com.google.inject.Inject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;

public class Ref {
  private static final Logger log = LoggerFactory.getLogger(Ref.class);
  private static Table table = new Table();

  private String project;
  private String ref;
  private String commit;
  private Date lastUpdated;

  public Ref(String project, String ref, String commit) {
    init(project, ref, commit, new Date());
  }

  public Ref(String project, String ref, String commit, Date date) {
    init(project, ref, commit, date);
  }

  private void init(String project, String ref, String commit, Date date) {
    this.project = project;
    this.ref = ref;
    this.commit = commit;
    this.lastUpdated = date;
  }

  public String getProject() {
    return project;
  }

  public String getRef() {
    return ref;
  }

  public String getCommit() {
    return commit;
  }

  public void setCommit(String commit) {
    this.commit = commit;
  }

  public Date getLastUpdated() {
    return lastUpdated;
  }

  public void save() {
    lastUpdated = new Date();
    log.debug(String.format("Saving Ref: %s, %s, %s", project, ref, commit));
    table.insertOrUpdate(this);
  }

  public void delete() {
    log.debug(String.format("Deleting Ref: %s, %s", project, ref));
    table.delete(this);
  }

  public static List<Ref> fetchByProject(String project) {
    return table.fetchByProject(project);
  }

  public static Ref fetchByRef(String project, String ref) {
    List<Ref> tmp = table.fetchByRef(project, ref);
    if (tmp.size() == 1) {
      return tmp.get(0);
    }
    return null;
  }

  /*
   * static interface Table { public void insertOrUpdate(Ref u); public
   * List<Ref> fetchByProject(String project); public List<Ref>
   * fetchByRef(String project, String ref); }
   *
   * public interface TableFactory { Table create(); }
   */

  static class Table {
    private static final String TABLE_NAME = "RefStatus";
    private static final String PROJECT = "project";
    private static final String REF = "ref";
    private static final String COMMIT = "commit";
    private static final String DATE = "last_update";
    @Inject
    private static SQLDriver sql;

    public Table() {
      // Create the table if it doesn't exist
      createTable();
    }

    private void createTable() {
      StringBuilder query = new StringBuilder();
      query.append(String.format("CREATE TABLE IF NOT EXISTS %s(", TABLE_NAME));
      query.append(String.format("%s VARCHAR(1023),", PROJECT));
      query.append(String.format("%s VARCHAR(255),", REF));
      query.append(String.format("%s VARCHAR(40),", COMMIT));
      query.append(String.format("%s TIMESTAMP DEFAULT NOW(),", DATE));
      query.append(String.format("PRIMARY KEY (%s, %s))", PROJECT, REF));
      try {
        sql.execute(query.toString());
      } catch (SQLException e) {
        log.error("Unable to create Ref table", e);
      }
    }

    public void insertOrUpdate(Ref r) {
      if (fetchByRef(r.getProject(), r.getRef()).isEmpty()) {
        String query = "INSERT INTO " + TABLE_NAME + "(" + PROJECT + ", " + REF
            + ", " + COMMIT + ", " + DATE + ") VALUES (?, ?, ?, "
            + sql.getDateFormat() + ")";
        try {
          sql.execute(query, r.getProject(), r.getRef(), r.getCommit(),
              sql.getDateAsString(r.getLastUpdated()));
        } catch (SQLException e) {
          log.error("Unable to insert reference", e);
        }
      } else {
        String query = "UPDATE " + TABLE_NAME + " SET " + COMMIT + "=?, " + DATE
            + "=" + sql.getDateFormat() + " WHERE " + PROJECT + "=? AND " + REF
            + "=?";
        try {
          sql.execute(query, r.getCommit(),
              sql.getDateAsString(r.getLastUpdated()), r.getProject(),
              r.getRef());
        } catch (SQLException e) {
          log.error("Unable to update reference", e);
        }
      }
    }

    public void delete(Ref r) {
      String query = "DELETE FROM " + TABLE_NAME + " WHERE " + PROJECT
          + "=? AND " + REF + "=?";
      try {
        sql.execute(query, r.getProject(), r.getRef());
      } catch (SQLException e) {
        log.error("Unable to delete reference", e);
      }
    }


    public List<Ref> fetchByProject(String project) {
      String query = "SELECT " + PROJECT + ", " + REF + ", " + COMMIT + ", "
          + DATE + " FROM " + TABLE_NAME + " WHERE " + PROJECT + "=?";
      try {
        return loadRefs(sql.fetchRows(query, project));

      } catch (SQLException e) {
        log.error("Unable to execute query", e);
      }
      return Collections.emptyList();
    }

    public List<Ref> fetchByRef(String project, String ref) {
      String query = "SELECT " + PROJECT + ", " + REF + ", " + COMMIT + ", "
          + DATE + " FROM " + TABLE_NAME + " WHERE " + PROJECT + "=? AND " + REF
          + "=?";
      try {
        return loadRefs(sql.fetchRows(query, project, ref));
      } catch (SQLException e) {
        log.error("Unable to execute query", e);
      }
      return Collections.emptyList();
    }

    private List<Ref> loadRefs(List<Map<String, String>> rows) {
      List<Ref> result = new ArrayList<>();
      for (Map<String, String> row : rows) {
        Ref tmp = new Ref(row.get(PROJECT), row.get(REF), row.get(COMMIT),
            sql.getStringAsDate(row.get(DATE)));
        result.add(tmp);
      }
      return result;
    }
  }
}
