package com.chenyang.druid.sql.ast.expr;

import com.chenyang.druid.FastsqlException;
import com.chenyang.druid.sql.SQLUtils;
import com.chenyang.druid.sql.ast.SQLDataType;
import com.chenyang.druid.sql.ast.SQLExpr;
import com.chenyang.druid.sql.ast.SQLExprComparor;
import com.chenyang.druid.sql.ast.SQLExprImpl;
import com.chenyang.druid.sql.ast.SQLName;
import com.chenyang.druid.sql.ast.SQLObject;
import com.chenyang.druid.sql.ast.SQLReplaceable;
import com.chenyang.druid.sql.ast.statement.SQLColumnDefinition;
import com.chenyang.druid.sql.ast.statement.SQLCreateProcedureStatement;
import com.chenyang.druid.sql.ast.statement.SQLExprTableSource;
import com.chenyang.druid.sql.ast.statement.SQLSelect;
import com.chenyang.druid.sql.ast.statement.SQLSelectItem;
import com.chenyang.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.chenyang.druid.sql.ast.statement.SQLSubqueryTableSource;
import com.chenyang.druid.sql.ast.statement.SQLTableSource;
import com.chenyang.druid.sql.ast.statement.SQLUnionQueryTableSource;
import com.chenyang.druid.sql.visitor.SQLASTVisitor;
import com.chenyang.druid.util.FnvHash;
import java.io.IOException;
import java.util.Collections;
import java.util.List;

public final class SQLPropertyExpr extends SQLExprImpl implements SQLName, SQLReplaceable, Comparable<SQLPropertyExpr> {
   private SQLExpr owner;
   private String name;
   protected long nameHashCod64;
   protected long hashCode64;
   protected SQLObject resolvedColumn;
   protected SQLObject resolvedOwnerObject;

   public SQLPropertyExpr(String owner2, String owner, String name) {
      this((SQLExpr)(new SQLPropertyExpr(owner2, owner)), name);
   }

   public SQLPropertyExpr(String owner, String name) {
      this((SQLExpr)(new SQLIdentifierExpr(owner)), name);
   }

   public SQLPropertyExpr(SQLExpr owner, String name) {
      this.setOwner(owner);
      this.name = name;
   }

   public SQLPropertyExpr(SQLExpr owner, String name, long nameHashCod64) {
      this.setOwner(owner);
      this.name = name;
      this.nameHashCod64 = nameHashCod64;
   }

   public SQLPropertyExpr() {
   }

   public String getSimpleName() {
      return this.name;
   }

   public SQLExpr getOwner() {
      return this.owner;
   }

   /** @deprecated */
   @Deprecated
   public String getOwnernName() {
      return this.owner instanceof SQLName ? ((SQLName)this.owner).toString() : null;
   }

   public String getOwnerName() {
      return this.owner instanceof SQLName ? ((SQLName)this.owner).toString() : null;
   }

   public void setOwner(SQLExpr owner) {
      if (owner != null) {
         owner.setParent(this);
      }

      if (this.parent instanceof SQLPropertyExpr) {
         SQLPropertyExpr propertyExpr = (SQLPropertyExpr)this.parent;
         propertyExpr.computeHashCode64();
      }

      this.owner = owner;
      this.hashCode64 = 0L;
   }

   protected void computeHashCode64() {
      long hash;
      if (this.owner instanceof SQLName) {
         hash = ((SQLName)this.owner).hashCode64();
         hash ^= 46L;
         hash *= 1099511628211L;
      } else if (this.owner == null) {
         hash = -3750763034362895579L;
      } else {
         hash = FnvHash.fnv1a_64_lower(this.owner.toString());
         hash ^= 46L;
         hash *= 1099511628211L;
      }

      hash = FnvHash.hashCode64(hash, this.name);
      this.hashCode64 = hash;
   }

   public void setOwner(String owner) {
      if (owner == null) {
         this.owner = null;
      } else {
         if (owner.indexOf(46) != -1) {
            SQLExpr ownerExpr = SQLUtils.toSQLExpr(owner);
            this.setOwner(ownerExpr);
         } else {
            this.setOwner((SQLExpr)(new SQLIdentifierExpr(owner)));
         }

      }
   }

   public String getName() {
      return this.name;
   }

   public void setName(String name) {
      this.name = name;
      this.hashCode64 = 0L;
      this.nameHashCod64 = 0L;
      if (this.parent instanceof SQLPropertyExpr) {
         SQLPropertyExpr propertyExpr = (SQLPropertyExpr)this.parent;
         propertyExpr.computeHashCode64();
      }

   }

   public void output(Appendable buf) {
      try {
         this.owner.output(buf);
         buf.append(".");
         buf.append(this.name);
      } catch (IOException ex) {
         throw new FastsqlException("output error", ex);
      }
   }

   protected void accept0(SQLASTVisitor visitor) {
      if (visitor.visit(this) && this.owner != null) {
         this.owner.accept(visitor);
      }

      visitor.endVisit(this);
   }

   public List getChildren() {
      return Collections.singletonList(this.owner);
   }

   public int hashCode() {
      long hash = this.hashCode64();
      return (int)(hash ^ hash >>> 32);
   }

   public long hashCode64() {
      if (this.hashCode64 == 0L) {
         this.computeHashCode64();
      }

      return this.hashCode64;
   }

   public boolean equals(SQLIdentifierExpr other) {
      if (other == null) {
         return false;
      } else if (this.nameHashCode64() != other.nameHashCode64()) {
         return false;
      } else {
         return this.resolvedOwnerObject != null && this.resolvedOwnerObject == other.getResolvedOwnerObject() && this.resolvedColumn != null && this.resolvedColumn == other.getResolvedColumn();
      }
   }

   public boolean equals(Object obj) {
      if (this == obj) {
         return true;
      } else if (obj == null) {
         return false;
      } else if (!(obj instanceof SQLPropertyExpr)) {
         return false;
      } else {
         SQLPropertyExpr other = (SQLPropertyExpr)obj;
         if (this.nameHashCode64() != other.nameHashCode64()) {
            return false;
         } else {
            if (this.owner == null) {
               if (other.owner != null) {
                  return false;
               }
            } else if (!this.owner.equals(other.owner)) {
               return false;
            }

            return true;
         }
      }
   }

   public SQLPropertyExpr clone() {
      SQLExpr owner_x = null;
      if (this.owner != null) {
         owner_x = this.owner.clone();
      }

      SQLPropertyExpr x = new SQLPropertyExpr(owner_x, this.name, this.nameHashCod64);
      x.hashCode64 = this.hashCode64;
      x.resolvedColumn = this.resolvedColumn;
      x.resolvedOwnerObject = this.resolvedOwnerObject;
      return x;
   }

   public boolean matchOwner(String alias) {
      return this.owner instanceof SQLIdentifierExpr ? ((SQLIdentifierExpr)this.owner).getName().equalsIgnoreCase(alias) : false;
   }

   public long nameHashCode64() {
      if (this.nameHashCod64 == 0L && this.name != null) {
         this.nameHashCod64 = FnvHash.hashCode64(this.name);
      }

      return this.nameHashCod64;
   }

   public String normalizedName() {
      String ownerName;
      if (this.owner instanceof SQLIdentifierExpr) {
         ownerName = ((SQLIdentifierExpr)this.owner).normalizedName();
      } else if (this.owner instanceof SQLPropertyExpr) {
         ownerName = ((SQLPropertyExpr)this.owner).normalizedName();
      } else {
         ownerName = this.owner.toString();
      }

      return ownerName + '.' + SQLUtils.normalize(this.name);
   }

   public SQLColumnDefinition getResolvedColumn() {
      if (this.resolvedColumn instanceof SQLColumnDefinition) {
         return (SQLColumnDefinition)this.resolvedColumn;
      } else {
         if (this.resolvedColumn instanceof SQLSelectItem) {
            SQLSelectItem selectItem = (SQLSelectItem)this.resolvedColumn;
            SQLExpr expr = selectItem.getExpr();
            if (expr instanceof SQLIdentifierExpr) {
               return ((SQLIdentifierExpr)expr).getResolvedColumn();
            }

            if (expr instanceof SQLPropertyExpr) {
               return ((SQLPropertyExpr)expr).getResolvedColumn();
            }
         }

         return null;
      }
   }

   public void setResolvedColumn(SQLColumnDefinition resolvedColumn) {
      this.resolvedColumn = resolvedColumn;
   }

   public void setResolvedColumn(SQLSelectItem resolvedColumn) {
      this.resolvedColumn = resolvedColumn;
   }

   public SQLTableSource getResolvedTableSource() {
      return this.resolvedOwnerObject instanceof SQLTableSource ? (SQLTableSource)this.resolvedOwnerObject : null;
   }

   public void setResolvedTableSource(SQLTableSource resolvedTableSource) {
      this.resolvedOwnerObject = resolvedTableSource;
   }

   public void setResolvedProcedure(SQLCreateProcedureStatement stmt) {
      this.resolvedOwnerObject = stmt;
   }

   public void setResolvedOwnerObject(SQLObject resolvedOwnerObject) {
      this.resolvedOwnerObject = resolvedOwnerObject;
   }

   public SQLCreateProcedureStatement getResolvedProcudure() {
      return this.resolvedOwnerObject instanceof SQLCreateProcedureStatement ? (SQLCreateProcedureStatement)this.resolvedOwnerObject : null;
   }

   public SQLObject getResolvedOwnerObject() {
      return this.resolvedOwnerObject;
   }

   public SQLDataType computeDataType() {
      if (this.resolvedColumn instanceof SQLColumnDefinition && this.resolvedColumn != null) {
         return ((SQLColumnDefinition)this.resolvedColumn).getDataType();
      } else if (this.resolvedColumn instanceof SQLSelectItem && this.resolvedColumn != null) {
         return ((SQLSelectItem)this.resolvedColumn).computeDataType();
      } else if (this.resolvedOwnerObject == null) {
         return null;
      } else {
         if (this.resolvedOwnerObject instanceof SQLSubqueryTableSource) {
            SQLSelect select = ((SQLSubqueryTableSource)this.resolvedOwnerObject).getSelect();
            SQLSelectQueryBlock queryBlock = select.getFirstQueryBlock();
            if (queryBlock == null) {
               return null;
            }

            SQLSelectItem selectItem = queryBlock.findSelectItem(this.nameHashCode64());
            if (selectItem != null) {
               return selectItem.computeDataType();
            }
         } else if (this.resolvedOwnerObject instanceof SQLUnionQueryTableSource) {
            SQLSelectQueryBlock queryBlock = ((SQLUnionQueryTableSource)this.resolvedOwnerObject).getUnion().getFirstQueryBlock();
            if (queryBlock == null) {
               return null;
            }

            SQLSelectItem selectItem = queryBlock.findSelectItem(this.nameHashCode64());
            if (selectItem != null) {
               return selectItem.computeDataType();
            }
         } else if (this.resolvedOwnerObject instanceof SQLExprTableSource) {
            SQLExpr expr = ((SQLExprTableSource)this.resolvedOwnerObject).getExpr();
            if (expr != null) {
            }
         }

         return null;
      }
   }

   public boolean nameEquals(String name) {
      return SQLUtils.nameEquals(this.name, name);
   }

   public SQLPropertyExpr simplify() {
      String normalizedName = SQLUtils.normalize(this.name);
      SQLExpr normalizedOwner = this.owner;
      if (normalizedOwner instanceof SQLIdentifierExpr) {
         normalizedOwner = ((SQLIdentifierExpr)normalizedOwner).simplify();
      }

      return normalizedName == this.name && normalizedOwner == this.owner ? this : new SQLPropertyExpr(normalizedOwner, normalizedName, this.hashCode64);
   }

   public String toString() {
      return this.owner == null ? this.name : this.owner.toString() + '.' + this.name;
   }

   public boolean replace(SQLExpr expr, SQLExpr target) {
      if (expr == this.owner) {
         this.setOwner(target);
         return true;
      } else {
         return false;
      }
   }

   public int compareTo(SQLPropertyExpr o) {
      int r = SQLExprComparor.compareTo(this.owner, o.owner);
      return r != 0 ? r : this.name.compareTo(o.name);
   }
}
