/*
 * Copyright 2015 Open Networking Laboratory
 *
 * 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 org.onosproject.ui.impl;

import org.onosproject.rest.AbstractInjectionResource;
import org.onosproject.ui.UiExtension;
import org.onosproject.ui.UiExtensionService;
import org.onosproject.ui.UiView;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static com.google.common.collect.ImmutableList.of;
import static com.google.common.io.ByteStreams.toByteArray;

/**
 * Resource for serving the dynamically composed nav.html.
 */
@Path("/")
public class MainNavResource extends AbstractInjectionResource {

    private static final String NAV_HTML = "nav.html";

    private static final String INJECT_VIEW_ITEMS_START =
            "<!-- {INJECTED-VIEW-NAV-START} -->";
    private static final String INJECT_VIEW_ITEMS_END =
            "<!-- {INJECTED-VIEW-NAV-END} -->";

    private static final String HDR_FORMAT =
            "<div class=\"nav-hdr\">%s</div>\n";
    private static final String NAV_FORMAT =
            "<a ng-click=\"navCtrl.hideNav()\" href=\"#/%s\">%s %s</a>\n";

    private static final String BLANK_GLYPH = "unknown";

    @GET
    @Produces(MediaType.TEXT_HTML)
    public Response getNavigation() throws IOException {
        UiExtensionService service = get(UiExtensionService.class);
        InputStream navTemplate =
                getClass().getClassLoader().getResourceAsStream(NAV_HTML);
        String html = new String(toByteArray(navTemplate));

        int p1s = split(html, 0, INJECT_VIEW_ITEMS_START);
        int p1e = split(html, 0, INJECT_VIEW_ITEMS_END);
        int p2s = split(html, p1e, null);

        StreamEnumeration streams =
                new StreamEnumeration(of(stream(html, 0, p1s),
                                         includeNavItems(service),
                                         stream(html, p1e, p2s)));

        return Response.ok(new SequenceInputStream(streams)).build();
    }

    // Produces an input stream of nav item injections from all extensions.
    private InputStream includeNavItems(UiExtensionService service) {
        List<UiExtension> extensions = service.getExtensions();
        StringBuilder sb = new StringBuilder("\n");

        for (UiView.Category cat : UiView.Category.values()) {
            if (cat == UiView.Category.HIDDEN) {
                continue;
            }

            List<UiView> catViews = getViewsForCat(extensions, cat);
            if (!catViews.isEmpty()) {
                addCatHeader(sb, cat);
                addCatItems(sb, catViews);
            }
        }

        return new ByteArrayInputStream(sb.toString().getBytes());
    }

    private List<UiView> getViewsForCat(List<UiExtension> extensions,
                                        UiView.Category cat) {
        List<UiView> views = new ArrayList<>();
        for (UiExtension extension : extensions) {
            views.addAll(extension.views().stream().filter(
                    view -> cat.equals(view.category())
            ).collect(Collectors.toList()));
        }
        return views;
    }

    private void addCatHeader(StringBuilder sb, UiView.Category cat) {
        sb.append(String.format(HDR_FORMAT, cat.label()));
    }

    private void addCatItems(StringBuilder sb, List<UiView> catViews) {
        for (UiView view : catViews) {
            sb.append(String.format(NAV_FORMAT, view.id(), icon(view), view.label()));
        }
    }

    private String icon(UiView view) {
        String gid = view.iconId() == null ? BLANK_GLYPH : view.iconId();
        return "<div icon icon-id=\"" + gid + "\"></div>";
    }
}
