/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.bookkeeper.server.http.service;

import static com.google.common.base.Charsets.UTF_8;
import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.collect.Maps;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import org.apache.bookkeeper.client.api.LedgerMetadata;
import org.apache.bookkeeper.common.util.JsonUtil;
import org.apache.bookkeeper.conf.ServerConfiguration;
import org.apache.bookkeeper.http.HttpServer;
import org.apache.bookkeeper.http.service.HttpEndpointService;
import org.apache.bookkeeper.http.service.HttpServiceRequest;
import org.apache.bookkeeper.http.service.HttpServiceResponse;
import org.apache.bookkeeper.meta.LedgerManager;
import org.apache.bookkeeper.meta.LedgerManagerFactory;
import org.apache.bookkeeper.meta.LedgerMetadataSerDe;
import org.apache.bookkeeper.proto.BookieServer;
import org.apache.bookkeeper.versioning.Versioned;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * HttpEndpointService that handle Bookkeeper list ledger related http request.
 *
 * <p>The GET method will list all ledger_ids in this bookkeeper cluster.
 * User can choose print metadata of each ledger or not by set parameter "print_metadata"
 */
public class ListLedgerService implements HttpEndpointService {

    static final Logger LOG = LoggerFactory.getLogger(ListLedgerService.class);

    protected ServerConfiguration conf;
    protected BookieServer bookieServer;
    private final LedgerMetadataSerDe serDe;

    public ListLedgerService(ServerConfiguration conf, BookieServer bookieServer) {
        checkNotNull(conf);
        this.conf = conf;
        this.bookieServer = bookieServer;
        this.serDe = new LedgerMetadataSerDe();

    }

    // Number of LedgerMetadata contains in each page
    static final int LIST_LEDGER_BATCH_SIZE = 100;

    private void keepLedgerMetadata(long ledgerId, CompletableFuture<Versioned<LedgerMetadata>> future,
                                    LinkedHashMap<String, String> output)
            throws Exception {
        LedgerMetadata md = future.get().getValue();
        output.put(Long.valueOf(ledgerId).toString(), new String(serDe.serialize(md), UTF_8));
    }

    @Override
    public HttpServiceResponse handle(HttpServiceRequest request) throws Exception {
        HttpServiceResponse response = new HttpServiceResponse();
        // GET
        // parameter could be like: print_metadata=true&page=PageIndex
        if (HttpServer.Method.GET == request.getMethod()) {
            Map<String, String> params = request.getParams();
            // default not print metadata
            boolean printMeta = (params != null)
              && params.containsKey("print_metadata")
              && params.get("print_metadata").equals("true");

            // Page index should start from 1;
            int pageIndex = (printMeta && params.containsKey("page"))
                ? Integer.parseInt(params.get("page")) : -1;

            LedgerManagerFactory mFactory = bookieServer.getBookie().getLedgerManagerFactory();
            LedgerManager manager = mFactory.newLedgerManager();
            LedgerManager.LedgerRangeIterator iter = manager.getLedgerRanges();

            // output <ledgerId: ledgerMetadata>
            LinkedHashMap<String, String> output = Maps.newLinkedHashMap();
            // futures for readLedgerMetadata for each page.
            Map<Long, CompletableFuture<Versioned<LedgerMetadata>>> futures =
                new LinkedHashMap<>(LIST_LEDGER_BATCH_SIZE);

            if (printMeta) {
                int ledgerIndex = 0;

                // start and end ledger index for wanted page.
                int startLedgerIndex = 0;
                int endLedgerIndex = 0;
                if (pageIndex > 0) {
                    startLedgerIndex = (pageIndex - 1) * LIST_LEDGER_BATCH_SIZE;
                    endLedgerIndex = startLedgerIndex + LIST_LEDGER_BATCH_SIZE - 1;
                }

                // get metadata
                while (iter.hasNext()) {
                    LedgerManager.LedgerRange r = iter.next();
                    for (Long lid : r.getLedgers()) {
                        ledgerIndex++;
                        if (endLedgerIndex == 0       // no actual page parameter provided
                                || (ledgerIndex >= startLedgerIndex && ledgerIndex <= endLedgerIndex)) {
                            futures.put(lid, manager.readLedgerMetadata(lid));
                        }
                    }
                    if (futures.size() >= LIST_LEDGER_BATCH_SIZE) {
                        for (Map.Entry<Long, CompletableFuture<Versioned<LedgerMetadata>> > e : futures.entrySet()) {
                            keepLedgerMetadata(e.getKey(), e.getValue(), output);
                        }
                        futures.clear();
                    }
                }
                for (Map.Entry<Long, CompletableFuture<Versioned<LedgerMetadata>> > e : futures.entrySet()) {
                    keepLedgerMetadata(e.getKey(), e.getValue(), output);
                }
                futures.clear();
            } else {
                while (iter.hasNext()) {
                    LedgerManager.LedgerRange r = iter.next();
                    for (Long lid : r.getLedgers()) {
                        output.put(lid.toString(), null);
                    }
                }
            }

            manager.close();

            String jsonResponse = JsonUtil.toJson(output);
            LOG.debug("output body:" + jsonResponse);
            response.setBody(jsonResponse);
            response.setCode(HttpServer.StatusCode.OK);
            return response;
        } else {
            response.setCode(HttpServer.StatusCode.NOT_FOUND);
            response.setBody("Not found method. Should be GET method");
            return response;
        }
    }
}
