// Copyright 2008 Google Inc.
//
// 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.gwtorm.schema;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gwtorm.schema.sql.SqlDialect;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.PrimaryKey;
import com.google.gwtorm.server.Relation;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;

public abstract class RelationModel {
  protected String methodName;
  protected String relationName;
  protected Relation relation;
  protected final Map<String, ColumnModel> fieldsByFieldName;
  protected final Map<String, ColumnModel> columnsByColumnName;
  protected final SortedMap<Integer, ColumnModel> columnsById;
  protected KeyModel primaryKey;
  protected Collection<QueryModel> queries;

  protected RelationModel() {
    fieldsByFieldName = Maps.newLinkedHashMap();
    columnsByColumnName = Maps.newLinkedHashMap();
    columnsById = Maps.newTreeMap();
    queries = Lists.newArrayList();
  }

  protected void initName(final String method, final Relation rel)
      throws OrmException {
    if (rel == null) {
      throw new OrmException("Method " + method + " is missing "
          + Relation.class.getName() + " annotation");
    }
    relation = rel;
    methodName = method;
    relationName = Util.any(relation.name(), Util.makeSqlFriendly(methodName));
  }

  protected void initColumns(final Collection<? extends ColumnModel> allFields)
      throws OrmException {
    for (final ColumnModel field : allFields) {
      if (fieldsByFieldName.put(field.getFieldName(), field) != null) {
        throw new OrmException("Duplicate fields " + field.getFieldName());
      }
      if (columnsById.put(field.getColumnID(), field) != null) {
        throw new OrmException("Duplicate @Column id " + field.getColumnID()
            + " in " + field.getPathToFieldName());
      }

      if (field.isNested()) {
        for (final ColumnModel newCol : field.getAllLeafColumns()) {
          registerColumn(newCol);
        }
      } else {
        registerColumn(field);
      }
    }
  }

  private void registerColumn(final ColumnModel nc) throws OrmException {
    final ColumnModel name = columnsByColumnName.put(nc.getColumnName(), nc);
    if (name != null) {
      throw new OrmException("Duplicate columns " + nc.getColumnName() + " in "
          + getMethodName() + ":\n" + "prior " + name.getPathToFieldName()
          + "\n next  " + nc.getPathToFieldName());
    }
  }

  protected void initPrimaryKey(final String name, final PrimaryKey annotation)
      throws OrmException {
    if (primaryKey != null) {
      throw new OrmException("Duplicate primary key definitions");
    }

    final ColumnModel field = getField(annotation.value());
    if (field == null) {
      throw new OrmException("Field " + annotation.value() + " not in "
          + getEntityTypeClassName());
    }

    primaryKey = new KeyModel(name, field);
    for (final ColumnModel c : primaryKey.getAllLeafColumns()) {
      c.inPrimaryKey = true;
    }
  }

  protected void addQuery(final QueryModel q) throws OrmException {
    for (QueryModel e : queries) {
      if (e.getName().equals(q.getName())) {
        throw new OrmException("Duplicate query " + q.getName() //
            + " in " + getAccessInterfaceName());
      }
    }
    queries.add(q);
  }


  public String getMethodName() {
    return methodName;
  }

  public String getRelationName() {
    return relationName;
  }

  public int getRelationID() {
    return relation.id();
  }

  public Collection<ColumnModel> getDependentFields() {
    final ArrayList<ColumnModel> r = new ArrayList<>();
    for (final ColumnModel c : fieldsByFieldName.values()) {
      if (!c.rowVersion && (primaryKey == null || primaryKey.getField() != c)) {
        r.add(c);
      }
    }
    return r;
  }

  public Collection<ColumnModel> getDependentColumns() {
    final ArrayList<ColumnModel> r = new ArrayList<>();
    for (final ColumnModel c : columnsByColumnName.values()) {
      if (!c.inPrimaryKey && !c.rowVersion) {
        r.add(c);
      }
    }
    return r;
  }

  public Collection<ColumnModel> getRowVersionFields() {
    final ArrayList<ColumnModel> r = new ArrayList<>();
    for (final ColumnModel c : fieldsByFieldName.values()) {
      if (c.rowVersion) {
        r.add(c);
      }
    }
    return r;
  }

  public Collection<ColumnModel> getRowVersionColumns() {
    final ArrayList<ColumnModel> r = new ArrayList<>();
    for (final ColumnModel c : columnsByColumnName.values()) {
      if (c.rowVersion) {
        r.add(c);
      }
    }
    return r;
  }

  public KeyModel getPrimaryKey() {
    return primaryKey;
  }

  public Collection<ColumnModel> getPrimaryKeyColumns() {
    if (getPrimaryKey() != null) {
      return getPrimaryKey().getAllLeafColumns();
    }
    return Collections.<ColumnModel> emptyList();
  }

  public Collection<QueryModel> getQueries() {
    return queries;
  }

  public Collection<ColumnModel> getColumns() {
    final ArrayList<ColumnModel> r = new ArrayList<>();
    r.addAll(getDependentColumns());
    r.addAll(getRowVersionColumns());
    r.addAll(getPrimaryKeyColumns());
    return r;
  }

  public Collection<ColumnModel> getFields() {
    return fieldsByFieldName.values();
  }

  public ColumnModel getField(final String name) {
    return fieldsByFieldName.get(name);
  }

  public ColumnModel getColumn(final String name) {
    return columnsByColumnName.get(name);
  }

  public String getCreateTableSql(final SqlDialect dialect) {
    final StringBuilder r = new StringBuilder();
    r.append("CREATE TABLE ");
    r.append(relationName);
    r.append(" (\n");

    for (final Iterator<ColumnModel> i = getColumns().iterator(); i.hasNext();) {
      final ColumnModel col = i.next();
      r.append(col.getColumnName());
      r.append(" ");
      r.append(dialect.getSqlTypeInfo(col).getSqlType(col, dialect));

      String check =
          dialect.getSqlTypeInfo(col).getCheckConstraint(col, dialect);
      if (check != null) {
        r.append(' ');
        r.append(check);
      }
      if (i.hasNext()) {
        r.append(",");
      }
      r.append("\n");
    }

    if (!getPrimaryKeyColumns().isEmpty()) {
      r.append(",PRIMARY KEY(");
      for (final Iterator<ColumnModel> i = getPrimaryKeyColumns().iterator(); i
          .hasNext();) {
        final ColumnModel col = i.next();
        r.append(col.getColumnName());
        if (i.hasNext()) {
          r.append(",");
        }
      }
      r.append(")\n");
    }

    r.append(")");
    dialect.appendCreateTableStorage(r, this);
    return r.toString();
  }

  public String getSelectSql(final SqlDialect dialect, final String tableAlias) {
    final StringBuilder r = new StringBuilder();
    r.append("SELECT ");
    for (final Iterator<ColumnModel> i = getColumns().iterator(); i.hasNext();) {
      final ColumnModel col = i.next();
      r.append(tableAlias);
      r.append('.');
      r.append(col.getColumnName());
      if (i.hasNext()) {
        r.append(",");
      }
    }
    r.append(" FROM ");
    r.append(relationName);
    r.append(' ');
    r.append(tableAlias);
    return r.toString();
  }

  public String getInsertOneSql(final SqlDialect dialect) {
    final StringBuilder r = new StringBuilder();
    r.append("INSERT INTO ");
    r.append(relationName);
    r.append("(");
    for (final Iterator<ColumnModel> i = getColumns().iterator(); i.hasNext();) {
      final ColumnModel col = i.next();
      r.append(col.getColumnName());
      if (i.hasNext()) {
        r.append(",");
      }
    }
    r.append(")VALUES(");
    int nth = 1;
    for (final Iterator<ColumnModel> i = getColumns().iterator(); i.hasNext();) {
      i.next();
      r.append(dialect.getParameterPlaceHolder(nth++));
      if (i.hasNext()) {
        r.append(",");
      }
    }
    r.append(")");
    return r.toString();
  }

  public String getUpdateOneSql(final SqlDialect dialect) {
    final StringBuilder r = new StringBuilder();
    r.append("UPDATE ");
    r.append(relationName);
    r.append(" SET ");
    List<ColumnModel> cols;
    int nth = 1;

    cols = new ArrayList<>();
    cols.addAll(getDependentColumns());
    cols.addAll(getRowVersionColumns());
    for (final Iterator<ColumnModel> i = cols.iterator(); i.hasNext();) {
      final ColumnModel col = i.next();
      r.append(col.getColumnName());
      r.append("=");
      r.append(dialect.getParameterPlaceHolder(nth++));
      if (i.hasNext()) {
        r.append(",");
      }
    }

    r.append(" WHERE ");
    cols = new ArrayList<>();
    cols.addAll(getPrimaryKeyColumns());
    cols.addAll(getRowVersionColumns());
    for (final Iterator<ColumnModel> i = cols.iterator(); i.hasNext();) {
      final ColumnModel col = i.next();
      r.append(col.getColumnName());
      r.append("=");
      r.append(dialect.getParameterPlaceHolder(nth++));
      if (i.hasNext()) {
        r.append(" AND ");
      }
    }
    return r.toString();
  }

  public String getDeleteOneSql(final SqlDialect dialect) {
    final StringBuilder r = new StringBuilder();
    r.append("DELETE FROM ");
    r.append(relationName);
    int nth = 1;
    r.append(" WHERE ");
    final List<ColumnModel> cols = new ArrayList<>();
    cols.addAll(getPrimaryKeyColumns());
    cols.addAll(getRowVersionColumns());
    for (final Iterator<ColumnModel> i = cols.iterator(); i.hasNext();) {
      final ColumnModel col = i.next();
      r.append(col.getColumnName());
      r.append("=");
      r.append(dialect.getParameterPlaceHolder(nth++));
      if (i.hasNext()) {
        r.append(" AND ");
      }
    }
    return r.toString();
  }

  public abstract String getAccessInterfaceName();

  public abstract String getEntityTypeClassName();

  @Override
  public String toString() {
    final StringBuilder r = new StringBuilder();
    r.append("Relation[\n");
    r.append("  method: " + getMethodName() + "\n");
    r.append("  table:  " + getRelationName() + "\n");
    r.append("  id:     " + getRelationID() + "\n");
    r.append("  access: " + getAccessInterfaceName() + "\n");
    r.append("  entity: " + getEntityTypeClassName() + "\n");
    r.append("]");
    return r.toString();
  }
}
