// 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.schema.QueryParser.Column;
import com.google.gwtorm.schema.sql.SqlBooleanTypeInfo;
import com.google.gwtorm.schema.sql.SqlDialect;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.Query;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.antlr.runtime.CommonToken;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.Tree;

public class QueryModel {
  private final RelationModel model;
  private final String name;
  private final Tree parsedQuery;

  public QueryModel(final RelationModel rel, final String queryName, final Query q)
      throws OrmException {
    this(rel, queryName, queryTextOf(queryName, q));
  }

  private static String queryTextOf(String queryName, Query q) throws OrmException {
    if (q == null) {
      throw new OrmException(
          "Query " + queryName + " is missing " + Query.class.getName() + " annotation");
    }
    return q.value();
  }

  public QueryModel(final RelationModel rel, final String queryName, final String queryText)
      throws OrmException {
    model = rel;
    name = queryName;

    try {
      parsedQuery = QueryParser.parse(model, queryText);
    } catch (QueryParseException e) {
      throw new OrmException("Cannot parse query " + queryText, e);
    }
  }

  public String getName() {
    return name;
  }

  public Tree getParseTree() {
    return parsedQuery;
  }

  public List<ColumnModel> getParameters() {
    final ArrayList<ColumnModel> r = new ArrayList<>();
    if (parsedQuery != null) {
      findParameters(r, parsedQuery);
    }
    return r;
  }

  public static class OrderBy {
    public final ColumnModel column;
    public final boolean descending;

    public OrderBy(ColumnModel column, boolean desc) {
      this.column = column;
      this.descending = desc;
    }

    @Override
    public int hashCode() {
      return column.hashCode();
    }

    @Override
    public boolean equals(Object other) {
      if (other instanceof OrderBy) {
        OrderBy o = (OrderBy) other;
        return column.equals(o.column) && descending == o.descending;
      }
      return false;
    }
  }

  public List<OrderBy> getOrderBy() {
    ArrayList<OrderBy> r = new ArrayList<>();
    if (parsedQuery != null) {
      Tree node = findOrderBy(parsedQuery);
      if (node != null) {
        for (int i = 0; i < node.getChildCount(); i++) {
          Tree sortOrder = node.getChild(i);
          Tree id = sortOrder.getChild(0);
          r.add(
              new OrderBy(
                  ((QueryParser.Column) id).getField(), sortOrder.getType() == QueryParser.DESC));
        }
      }
    }
    return r;
  }

  private void findParameters(final List<ColumnModel> r, final Tree node) {
    switch (node.getType()) {
      case QueryParser.WHERE:
        extractParameters(r, node);
        break;

      default:
        for (int i = 0; i < node.getChildCount(); i++) {
          findParameters(r, node.getChild(i));
        }
        break;
    }
  }

  private void extractParameters(final List<ColumnModel> r, final Tree node) {
    switch (node.getType()) {
      case QueryParser.LT:
      case QueryParser.LE:
      case QueryParser.GT:
      case QueryParser.GE:
      case QueryParser.EQ:
        if (node.getChild(1).getType() == QueryParser.PLACEHOLDER) {
          r.add(((QueryParser.Column) node.getChild(0)).getField());
        }
        break;

      default:
        for (int i = 0; i < node.getChildCount(); i++) {
          extractParameters(r, node.getChild(i));
        }
        break;
    }
  }

  public boolean hasWhere() {
    return findWhere(parsedQuery) != null;
  }

  public boolean hasOrderBy() {
    return findOrderBy(parsedQuery) != null;
  }

  public boolean hasLimit() {
    return findLimit(parsedQuery) != null;
  }

  public boolean hasLimitParameter() {
    final Tree limit = findLimit(parsedQuery);
    return limit != null && limit.getChild(0).getType() == QueryParser.PLACEHOLDER;
  }

  public int getStaticLimit() {
    return Integer.parseInt(findLimit(parsedQuery).getChild(0).getText());
  }

  private Tree findWhere(final Tree node) {
    if (node == null) {
      return null;
    }
    switch (node.getType()) {
      case QueryParser.WHERE:
        return node;
      default:
        for (int i = 0; i < node.getChildCount(); i++) {
          final Tree r = findLimit(node.getChild(i));
          if (r != null) {
            return r;
          }
        }
        return null;
    }
  }

  private Tree findLimit(final Tree node) {
    if (node == null) {
      return null;
    }
    switch (node.getType()) {
      case QueryParser.LIMIT:
        return node;
      default:
        for (int i = 0; i < node.getChildCount(); i++) {
          final Tree r = findLimit(node.getChild(i));
          if (r != null) {
            return r;
          }
        }
        return null;
    }
  }

  private Tree findOrderBy(final Tree node) {
    if (node == null) {
      return null;
    }
    switch (node.getType()) {
      case QueryParser.ORDER:
        return node;
      default:
        for (int i = 0; i < node.getChildCount(); i++) {
          final Tree r = findOrderBy(node.getChild(i));
          if (r != null) {
            return r;
          }
        }
        return null;
    }
  }

  public String getSelectSql(final SqlDialect dialect, final String tableAlias) {
    final StringBuilder buf = new StringBuilder();
    buf.append(model.getSelectSql(dialect, tableAlias));
    if (parsedQuery != null) {
      final FormatInfo fmt = new FormatInfo(buf, dialect, tableAlias);
      final Tree t = expand(parsedQuery);
      if (t.getType() == 0) {
        formatChilden(fmt, t);
      } else {
        format(fmt, t);
      }
    }
    return buf.toString();
  }

  private void formatChilden(final FormatInfo fmt, final Tree node) {
    for (int i = 0; i < node.getChildCount(); i++) {
      format(fmt, node.getChild(i));
    }
  }

  private void format(final FormatInfo fmt, final Tree node) {
    switch (node.getType()) {
      case QueryParser.WHERE:
        fmt.buf.append(" WHERE ");
        formatChilden(fmt, node);
        break;

      case QueryParser.AND:
        for (int i = 0; i < node.getChildCount(); i++) {
          if (i > 0) {
            fmt.buf.append(" AND ");
          }
          format(fmt, node.getChild(i));
        }
        break;

      case QueryParser.LT:
      case QueryParser.LE:
      case QueryParser.GT:
      case QueryParser.GE:
      case QueryParser.EQ:
        format(fmt, node.getChild(0));
        fmt.buf.append(node.getText());
        format(fmt, node.getChild(1));
        break;

      case QueryParser.ID:
        {
          final ColumnModel col = ((QueryParser.Column) node).getField();
          if (!col.isSqlPrimitive()) {
            throw new IllegalStateException("Unexpanded nested field");
          }
          fmt.buf.append(fmt.tableAlias);
          fmt.buf.append('.');
          fmt.buf.append(col.getColumnName());
          break;
        }

      case QueryParser.PLACEHOLDER:
        fmt.buf.append(fmt.dialect.getParameterPlaceHolder(fmt.nthParam++));
        break;

      case QueryParser.TRUE:
        fmt.buf.append(
            ((SqlBooleanTypeInfo) fmt.dialect.getSqlTypeInfo(Boolean.TYPE)).getTrueLiteralValue());
        break;

      case QueryParser.FALSE:
        fmt.buf.append(
            ((SqlBooleanTypeInfo) fmt.dialect.getSqlTypeInfo(Boolean.TYPE)).getFalseLiteralValue());
        break;

      case QueryParser.CONSTANT_INTEGER:
      case QueryParser.CONSTANT_STRING:
        fmt.buf.append(node.getText());
        break;

      case QueryParser.ORDER:
        fmt.buf.append(" ORDER BY ");
        for (int i = 0; i < node.getChildCount(); i++) {
          final Tree sortOrder = node.getChild(i);
          final Tree id = sortOrder.getChild(0);
          if (i > 0) {
            fmt.buf.append(',');
          }
          final ColumnModel col = ((QueryParser.Column) id).getField();
          if (col.isNested()) {
            for (final Iterator<ColumnModel> cItr = col.getAllLeafColumns().iterator();
                cItr.hasNext();
                ) {
              fmt.buf.append(fmt.tableAlias);
              fmt.buf.append('.');
              fmt.buf.append(cItr.next().getColumnName());
              if (sortOrder.getType() == QueryParser.DESC) {
                fmt.buf.append(" DESC");
              }
              if (cItr.hasNext()) {
                fmt.buf.append(',');
              }
            }
          } else {
            fmt.buf.append(fmt.tableAlias);
            fmt.buf.append('.');
            fmt.buf.append(col.getColumnName());
            if (sortOrder.getType() == QueryParser.DESC) {
              fmt.buf.append(" DESC");
            }
          }
        }
        break;

      case QueryParser.LIMIT:
        if (fmt.dialect.selectHasLimit()) {
          final Tree p = node.getChild(0);
          if (p.getType() == QueryParser.CONSTANT_INTEGER
              || p.getType() == QueryParser.PLACEHOLDER) {
            fmt.buf.append(' ');
            fmt.buf.append(fmt.dialect.getLimitSql(p.getText()));
          }
        }
        break;

      default:
        throw new IllegalStateException("Unsupported query token");
    }
  }

  @Override
  public String toString() {
    return "Query[" + name + " " + getParseTree().toStringTree() + "]";
  }

  private Tree expand(final Tree node) {
    switch (node.getType()) {
      case QueryParser.LT:
      case QueryParser.LE:
      case QueryParser.GT:
      case QueryParser.GE:
      case QueryParser.EQ:
        {
          final Column qpc = (QueryParser.Column) node.getChild(0);
          final ColumnModel f = qpc.getField();
          if (f.isNested()) {
            final CommonTree join;

            join = new CommonTree(new CommonToken(QueryParser.AND));
            for (final ColumnModel c : f.getAllLeafColumns()) {
              final Tree op;

              op = node.dupNode();
              op.addChild(new QueryParser.Column(qpc, c));
              op.addChild(node.getChild(1).dupNode());
              join.addChild(op);
            }
            return join;
          }
        }
    }

    final Tree r = node.dupNode();
    for (int i = 0; i < node.getChildCount(); i++) {
      r.addChild(expand(node.getChild(i)));
    }
    return r;
  }

  static class FormatInfo {
    final StringBuilder buf;
    final SqlDialect dialect;
    final String tableAlias;
    int nthParam = 1;

    FormatInfo(StringBuilder r, SqlDialect dialect, String tableAlias) {
      this.buf = r;
      this.dialect = dialect;
      this.tableAlias = tableAlias;
    }
  }
}
