package util.sqlparse.visitor.mongo;

import com.alibaba.druid.sql.dialect.mongo.parser.ApiTreeParser;

public class MongoParser {
   private final MongoVisitor visitor;

   public MongoParser(MongoVisitor visitor) {
      this.visitor = visitor;
   }

   public void parse(MongoNode ctx) {
      if (ctx.type() != BsonNode.BsonNodeType.Basic) {
         if (ctx.type() == BsonNode.BsonNodeType.Object) {
            this.parse((BsonObjectNode)ctx, ctx);
         } else if (ctx.type() == BsonNode.BsonNodeType.Array) {
            BsonArrayNode array = (BsonArrayNode)ctx;
            MongoNode node = array.get(array.size() - 1);
            if (node.type() == BsonNode.BsonNodeType.Object) {
               this.parse((BsonObjectNode)node, ctx);
            }
         }

      }
   }

   private void parse(BsonObjectNode judge, MongoNode entry) {
      if (judge.contains(Identifier.FindAndModify.code)) {
         this.visitor.visitFindAndModify(entry);
      } else if (judge.contains(Identifier.Find.code)) {
         this.visitor.visitFind(entry);
      } else if (judge.contains(Identifier.UpdateUser.code)) {
         this.visitor.visitUpdateUser(entry);
      } else if (judge.contains(Identifier.Insert.code)) {
         this.visitor.visitInsert(entry);
      } else if (judge.contains(Identifier.Update.code)) {
         this.visitor.visitUpdate(entry);
      } else if (judge.contains(Identifier.Delete.code)) {
         this.visitor.visitDelete(entry);
      } else if (judge.contains(Identifier.Count.code)) {
         this.visitor.visitCount(entry);
      } else if (judge.contains(Identifier.Aggregate.code)) {
         this.visitor.visitAggregate(entry);
      } else if (judge.contains(Identifier.Distinct.code)) {
         this.visitor.visitDistinct(entry);
      } else if (judge.contains(Identifier.DropUser.code)) {
         this.visitor.visitDropUser(entry);
      } else if (judge.contains(Identifier.CreateIndexes.code)) {
         this.visitor.visitCreateIndexes(entry);
      } else if (judge.contains(Identifier.DropIndexes.code)) {
         this.visitor.visitDropIndexes(entry);
      } else if (judge.contains(Identifier.ReIndex.code)) {
         this.visitor.visitReIndex(entry);
      } else if (judge.contains(Identifier.RenameCollection.code)) {
         this.visitor.visitRenameCollection(entry);
      } else if (judge.contains(Identifier.Mapreduce.code)) {
         this.visitor.visitMapreduce(entry);
      } else if (judge.contains(Identifier.CreateUser.code)) {
         this.visitor.visitCreateUser(entry);
      } else if (judge.contains(Identifier.SaslSupportedMechs.code)) {
         this.visitor.visitSaslSupportedMechs(entry);
      } else if (judge.contains(Identifier.UsersInfo.code)) {
         this.visitor.visitUsersInfo(entry);
      } else if (judge.contains(Identifier.GrantRolesToUser.code)) {
         this.visitor.visitGrantRolesToUser(entry);
      } else if (judge.contains(Identifier.RevokeRolesFromUser.code)) {
         this.visitor.visitRevokeRolesFromUser(entry);
      } else if (judge.contains(Identifier.Drop.code)) {
         this.visitor.visitDrop(entry);
      } else if (judge.contains(Identifier.Create.code)) {
         this.visitor.visitCreate(entry);
      }

   }

   public String encode() {
      Encoder visitor = (Encoder)this.visitor;
      String api = visitor.getApi();
      ApiTreeParser apiTreeParser = new ApiTreeParser(api);
      apiTreeParser.parse();
      visitor.setApiTreeParser(apiTreeParser);
      new BsonObjectNode();
      String methodName = apiTreeParser.getMethod().getName();
      Object out;
      if (apiTreeParser.getCollection() != null) {
         if (Identifier.Find.code.equals(methodName)) {
            out = new BsonObjectNode();
            visitor.visitFind((MongoNode)out);
         } else if (Identifier.FindOne.code.equals(methodName)) {
            out = new BsonObjectNode();
            visitor.visitFindOne((MongoNode)out);
         } else if (Identifier.Insert.code.equals(methodName)) {
            out = new BsonArrayNode();
            visitor.visitInsert((MongoNode)out);
         } else if (Identifier.InsertOne.code.equals(methodName)) {
            out = new BsonArrayNode();
            visitor.visitInsertOne((MongoNode)out);
         } else if (Identifier.InsertMany.code.equals(methodName)) {
            out = new BsonArrayNode();
            visitor.visitInsertMany((MongoNode)out);
         } else if (Identifier.Distinct.code.equals(methodName)) {
            out = new BsonObjectNode();
            visitor.visitDistinct((MongoNode)out);
         } else if (Identifier.Update.code.equals(methodName)) {
            out = new BsonArrayNode();
            visitor.visitUpdate((MongoNode)out);
         } else if (Identifier.UpdateOne.code.equals(methodName)) {
            out = new BsonArrayNode();
            visitor.visitUpdateOne((MongoNode)out);
         } else if (Identifier.UpdateMany.code.equals(methodName)) {
            out = new BsonArrayNode();
            visitor.visitUpdateMany((MongoNode)out);
         } else if (Identifier.Save.code.equals(methodName)) {
            out = new BsonArrayNode();
            visitor.visitSave((MongoNode)out);
         } else if (Identifier.Remove.code.equals(methodName)) {
            out = new BsonArrayNode();
            visitor.visitDelete((MongoNode)out);
         } else if (Identifier.DeleteOne.code.equals(methodName)) {
            out = new BsonArrayNode();
            visitor.visitDeleteOne((MongoNode)out);
         } else if (Identifier.DeleteMany.code.equals(methodName)) {
            out = new BsonArrayNode();
            visitor.visitDeleteMany((MongoNode)out);
         } else if (Identifier.Aggregate.code.equals(methodName)) {
            out = new BsonObjectNode();
            visitor.visitAggregate((MongoNode)out);
         } else if (Identifier.Count.code.equals(methodName)) {
            out = new BsonObjectNode();
            visitor.visitCount((MongoNode)out);
         } else if (Identifier.findAndModify.code.equals(methodName)) {
            out = new BsonObjectNode();
            visitor.visitFindAndModify((MongoNode)out);
         } else if (Identifier.FindOneAndUpdate.code.equals(methodName)) {
            out = new BsonObjectNode();
            visitor.findOneAndUpdate((MongoNode)out);
         } else if (Identifier.FindOneAndReplace.code.equals(methodName)) {
            out = new BsonObjectNode();
            visitor.findOneAndReplace((MongoNode)out);
         } else if (Identifier.FindOneAndDelete.code.equals(methodName)) {
            out = new BsonObjectNode();
            visitor.findOneAndDelete((MongoNode)out);
         } else if (Identifier.MapReduce.code.equals(methodName)) {
            out = new BsonObjectNode();
            visitor.visitMapreduce((MongoNode)out);
         } else if (Identifier.CreateIndexes.code.equals(methodName)) {
            out = new BsonObjectNode();
            visitor.visitCreateIndexes((MongoNode)out);
         } else if (Identifier.CreateIndex.code.equals(methodName)) {
            out = new BsonObjectNode();
            visitor.visitCreateIndexes((MongoNode)out);
         } else if (Identifier.DropIndex.code.equals(methodName)) {
            out = new BsonObjectNode();
            visitor.visitDropIndexes((MongoNode)out);
         } else if (Identifier.DropIndexes.code.equals(methodName)) {
            out = new BsonObjectNode();
            visitor.visitDropIndexes((MongoNode)out);
         } else if (Identifier.ReIndex.code.equals(methodName)) {
            out = new BsonObjectNode();
            visitor.visitReIndex((MongoNode)out);
         } else if (Identifier.GetIndexes.code.equals(methodName)) {
            out = new BsonObjectNode();
            visitor.visitGetIndexes((MongoNode)out);
         } else if (Identifier.RenameCollection.code.equals(methodName)) {
            out = new BsonObjectNode();
            visitor.visitRenameCollection((MongoNode)out);
         } else if (Identifier.Drop.code.equals(methodName)) {
            out = new BsonObjectNode();
            visitor.visitDrop((MongoNode)out);
         } else {
            if (!Identifier.CountDocuments.code.equals(methodName)) {
               return "";
            }

            out = new BsonObjectNode();
            visitor.visitCountDocuments((MongoNode)out);
         }
      } else if (Identifier.CreateCollection.code.equals(methodName)) {
         out = new BsonObjectNode();
         visitor.visitCreateCollection((MongoNode)out);
      } else if (Identifier.CreateUser.code.equals(methodName)) {
         out = new BsonObjectNode();
         visitor.visitCreateUser((MongoNode)out);
      } else if (Identifier.ChangeUserPassword.code.equals(methodName)) {
         out = new BsonObjectNode();
         visitor.visitChangeUserPassword((MongoNode)out);
      } else if (Identifier.GetUser.code.equals(methodName)) {
         out = new BsonObjectNode();
         visitor.visitUsersInfo((MongoNode)out);
      } else if (Identifier.GrantRolesToUser.code.equals(methodName)) {
         out = new BsonObjectNode();
         visitor.visitGrantRolesToUser((MongoNode)out);
      } else if (Identifier.RemoveUser.code.equals(methodName)) {
         out = new BsonObjectNode();
         visitor.visitDropUser((MongoNode)out);
      } else if (Identifier.DropUser.code.equals(methodName)) {
         out = new BsonObjectNode();
         visitor.visitDropUser((MongoNode)out);
      } else if (Identifier.UpdateUser.code.equals(methodName)) {
         out = new BsonObjectNode();
         visitor.visitUpdateUser((MongoNode)out);
      } else if (Identifier.RevokeRolesFromUser.code.equals(methodName)) {
         out = new BsonObjectNode();
         visitor.visitRevokeRolesFromUser((MongoNode)out);
      } else {
         if (!Identifier.RunCommand.code.equals(methodName)) {
            return "";
         }

         out = new BsonObjectNode();
         visitor.visitRunCommand((MongoNode)out);
      }

      return out.toString();
   }
}
