// 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<ColumnModel>();
    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<ColumnModel>();
    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<ColumnModel>();
    for (final ColumnModel c : fieldsByFieldName.values()) {
      if (c.rowVersion) {
        r.add(c);
      }
    }
    return r;
  }

  public Collection<ColumnModel> getRowVersionColumns() {
    final ArrayList<ColumnModel> r = new ArrayList<ColumnModel>();
    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<ColumnModel>();
    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<ColumnModel>();
    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<ColumnModel>();
    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<ColumnModel>();
    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();
  }
}
