/*
 * 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 com.google.common.collect.ImmutableList;
import org.onosproject.ui.UiExtension;
import org.onosproject.ui.UiExtensionService;

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.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;

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

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

    private static final String INDEX = "templates/index-template.html";

    private static final String INJECT_CSS_START = "<!-- {INJECTED-STYLESHEETS-START} -->";
    private static final String INJECT_CSS_END = "<!-- {INJECTED-STYLESHEETS-END} -->";

    private static final String INJECT_JS_START = "<!-- {INJECTED-JAVASCRIPT-START} -->";
    private static final String INJECT_JS_END = "<!-- {INJECTED-JAVASCRIPT-END} -->";

    @GET
    @Produces(MediaType.TEXT_HTML)
    public Response getMainIndex() throws IOException {
        UiExtensionService service = get(UiExtensionService.class);
        InputStream indexTemplate = getClass().getClassLoader().getResourceAsStream(INDEX);
        String index = new String(toByteArray(indexTemplate));

        int p1s = split(index, 0, INJECT_JS_START);
        int p1e = split(index, p1s, INJECT_JS_END);
        int p2s = split(index, p1e, INJECT_CSS_START);
        int p2e = split(index, p2s, INJECT_CSS_END);
        int p3s = split(index, p2e, null);

        StreamEnumeration streams =
                new StreamEnumeration(of(stream(index, 0, p1s),
                                         includeJs(service),
                                         stream(index, p1e, p2s),
                                         includeCss(service),
                                         stream(index, p2e, p3s)));

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

    // Produces an input stream including CSS injections from all extensions.
    private InputStream includeCss(UiExtensionService service) {
        ImmutableList.Builder<InputStream> builder = ImmutableList.builder();
        for (UiExtension extension : service.getExtensions()) {
            builder.add(extension.css());
        }
        return new SequenceInputStream(new StreamEnumeration(builder.build()));
    }

    // Produces an input stream including JS injections from all extensions.
    private InputStream includeJs(UiExtensionService service) {
        ImmutableList.Builder<InputStream> builder = ImmutableList.builder();
        for (UiExtension extension : service.getExtensions()) {
            builder.add(extension.js());
        }
        return new SequenceInputStream(new StreamEnumeration(builder.build()));
    }

}
