/* (non-Javadoc)
   * @see cn.com.rebirth.search.core.rest.RestHandler#handleRequest(cn.com.rebirth.search.core.rest.RestRequest, cn.com.rebirth.search.core.rest.RestChannel)
   */
  @Override
  public void handleRequest(final RestRequest request, final RestChannel channel) {
    PercolateRequest percolateRequest =
        new PercolateRequest(request.param("index"), request.param("type"));
    percolateRequest.source(
        request.contentByteArray(),
        request.contentByteArrayOffset(),
        request.contentLength(),
        request.contentUnsafe());

    percolateRequest.listenerThreaded(false);

    percolateRequest.operationThreaded(true);

    percolateRequest.preferLocal(
        request.paramAsBoolean("prefer_local", percolateRequest.preferLocalShard()));
    client.percolate(
        percolateRequest,
        new ActionListener<PercolateResponse>() {
          @Override
          public void onResponse(PercolateResponse response) {
            try {
              XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
              builder.startObject();

              builder.field(Fields.OK, true);
              builder.startArray(Fields.MATCHES);
              for (String match : response) {
                builder.value(match);
              }
              builder.endArray();

              builder.endObject();

              channel.sendResponse(new XContentRestResponse(request, RestStatus.OK, builder));
            } catch (Exception e) {
              onFailure(e);
            }
          }

          @Override
          public void onFailure(Throwable e) {
            try {
              channel.sendResponse(new XContentThrowableRestResponse(request, e));
            } catch (IOException e1) {
              logger.error("Failed to send failure response", e1);
            }
          }
        });
  }
  /* (non-Javadoc)
   * @see cn.com.rebirth.search.core.rest.RestHandler#handleRequest(cn.com.rebirth.search.core.rest.RestRequest, cn.com.rebirth.search.core.rest.RestChannel)
   */
  @Override
  public void handleRequest(final RestRequest request, final RestChannel channel) {
    final String[] indices = splitIndices(request.param("index"));
    final Set<String> types = ImmutableSet.copyOf(splitTypes(request.param("type")));

    ClusterStateRequest clusterStateRequest =
        Requests.clusterStateRequest()
            .filterRoutingTable(true)
            .filterNodes(true)
            .filteredIndices(indices);

    client
        .admin()
        .cluster()
        .state(
            clusterStateRequest,
            new ActionListener<ClusterStateResponse>() {
              @Override
              public void onResponse(ClusterStateResponse response) {
                try {
                  MetaData metaData = response.state().metaData();
                  XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
                  builder.startObject();

                  if (indices.length == 1 && types.size() == 1) {
                    if (metaData.indices().isEmpty()) {
                      channel.sendResponse(
                          new XContentThrowableRestResponse(
                              request, new IndexMissingException(new Index(indices[0]))));
                      return;
                    }
                    boolean foundType = false;
                    IndexMetaData indexMetaData = metaData.iterator().next();
                    for (MappingMetaData mappingMd : indexMetaData.mappings().values()) {
                      if (!types.isEmpty() && !types.contains(mappingMd.type())) {

                        continue;
                      }
                      foundType = true;
                      builder.field(mappingMd.type());
                      builder.map(mappingMd.sourceAsMap());
                    }
                    if (!foundType) {
                      channel.sendResponse(
                          new XContentThrowableRestResponse(
                              request,
                              new TypeMissingException(
                                  new Index(indices[0]), types.iterator().next())));
                      return;
                    }
                  } else {
                    for (IndexMetaData indexMetaData : metaData) {
                      builder.startObject(
                          indexMetaData.index(), XContentBuilder.FieldCaseConversion.NONE);

                      for (MappingMetaData mappingMd : indexMetaData.mappings().values()) {
                        if (!types.isEmpty() && !types.contains(mappingMd.type())) {

                          continue;
                        }
                        builder.field(mappingMd.type());
                        builder.map(mappingMd.sourceAsMap());
                      }

                      builder.endObject();
                    }
                  }

                  builder.endObject();

                  channel.sendResponse(new XContentRestResponse(request, OK, builder));
                } catch (Exception e) {
                  onFailure(e);
                }
              }

              @Override
              public void onFailure(Throwable e) {
                try {
                  channel.sendResponse(new XContentThrowableRestResponse(request, e));
                } catch (IOException e1) {
                  logger.error("Failed to send failure response", e1);
                }
              }
            });
  }