// 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.gwtorm.client.OrmException;
import com.google.gwtorm.client.PrimaryKey;
import com.google.gwtorm.client.Relation;
import com.google.gwtorm.client.SecondaryKey;
import com.google.gwtorm.schema.sql.SqlDialect;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;

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

  protected RelationModel() {
    fieldsByFieldName = new LinkedHashMap<String, ColumnModel>();
    columnsByColumnName = new LinkedHashMap<String, ColumnModel>();
    secondaryKeys = new ArrayList<KeyModel>();
    queries = new ArrayList<QueryModel>();
  }

  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 (field.isNested()) {
        for (final ColumnModel newCol : field.getAllLeafColumns()) {
          registerColumn(newCol);
        }
      } else {
        registerColumn(field);
      }
    }
  }

  private void registerColumn(final ColumnModel nc) throws OrmException {
    final ColumnModel oc = columnsByColumnName.put(nc.getColumnName(), nc);
    if (oc != null) {
      throw new OrmException("Duplicate columns " + nc.getColumnName() + " in "
          + getMethodName() + ":\n" + "prior " + oc.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 addSecondaryKey(final String name,
      final SecondaryKey annotation) throws OrmException {
    final ColumnModel field = getField(annotation.value());
    if (field == null) {
      throw new OrmException("Field " + annotation.value() + " not in "
          + getEntityTypeClassName());
    }

    secondaryKeys.add(new KeyModel(name, field));
  }

  protected void addQuery(final QueryModel q) {
    queries.add(q);
  }


  public String getMethodName() {
    return methodName;
  }

  public String getRelationName() {
    return relationName;
  }

  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<KeyModel> getSecondaryKeys() {
    return secondaryKeys;
  }

  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 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));
      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");
    }

    for (final KeyModel key : secondaryKeys) {
      r.append(",UNIQUE(");
      for (final Iterator<ColumnModel> i = key.getAllLeafColumns().iterator(); i
          .hasNext();) {
        final ColumnModel col = i.next();
        r.append(col.getColumnName());
        if (i.hasNext()) {
          r.append(",");
        }
      }
      r.append(")\n");
    }

    r.append(")");
    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("  access: " + getAccessInterfaceName() + "\n");
    r.append("  entity: " + getEntityTypeClassName() + "\n");
    r.append("]");
    return r.toString();
  }
}
