package com.github.ruediste.rise.api;

import java.io.ByteArrayOutputStream;
import java.util.function.Consumer;

import javax.inject.Inject;
import javax.inject.Provider;

import com.github.ruediste.rendersnakeXT.canvas.HtmlCanvas;
import com.github.ruediste.rise.core.ActionResult;
import com.github.ruediste.rise.core.CurrentLocale;
import com.github.ruediste.rise.core.IController;
import com.github.ruediste.rise.core.actionInvocation.ActionInvocationBuilderKnownController;
import com.github.ruediste.rise.integration.RiseCanvasBase;
import com.github.ruediste.rise.mvc.IControllerMvc;
import com.github.ruediste.rise.mvc.MvcUtil;
import com.github.ruediste1.i18n.lString.LString;
import com.github.ruediste1.i18n.label.LabelUtil;
import com.google.common.reflect.TypeToken;

/**
 * Base Class for views of the MVC framework.
 * 
 * <p>
 * Since each application will use it's own {@link HtmlCanvas} subclass, the
 * method called to render the view takes a {@link ByteArrayOutputStream} as
 * argument ({@link #render(ByteArrayOutputStream)}). Each application is
 * supposed to create a subclass called {@code ViewMvc} which
 * <ul>
 * <li>defines an abstract method {@code render(AppSpecificCanvas)}</li>
 * <li>implement {@link #render(ByteArrayOutputStream)} by creating a canvas
 * instance and invoking
 * {@link #render(ByteArrayOutputStream, RiseCanvasBase, Consumer)}, with the
 * consumer invoking the defined {@code render method}
 * </ul>
 * 
 * Sample:
 * 
 * <pre>
 * &#064;{@code Inject
 * Provider<SampleCanvas> canvasProvider;
 * }
 * 
 * &#064;{@code Override
 * public void render(ByteArrayOutputStream out) throws IOException {
 *     render(out, canvasProvider.get(), this::render);
 * }
 * 
 * protected abstract void render(SampleCanvas html);
 * }
 * </pre>
 */
public abstract class ViewMvcBase<TController extends IControllerMvc, TData, TCanvas extends RiseCanvasBase<?>> {

    @Inject
    private MvcUtil util;

    @Inject
    Provider<TCanvas> canvasProvider;

    @Inject
    LabelUtil labelUtil;

    @Inject
    CurrentLocale currentLocale;

    private TData data;

    private Class<? extends TController> controllerClass;

    @SuppressWarnings({ "unchecked", "rawtypes" })
    protected ViewMvcBase() {
        controllerClass = (Class) TypeToken.of(getClass())
                .resolveType(ViewMvcBase.class.getTypeParameters()[0])
                .getRawType();
    }

    public void setControllerClass(
            Class<? extends TController> controllerClass) {
        this.controllerClass = controllerClass;
    }

    public final void initialize(TData data) {
        this.data = data;
    }

    public final TData data() {
        return data;
    }

    public void render(ByteArrayOutputStream out) {
        TCanvas canvas = canvasProvider.get();
        canvas.initializeForOutput(out);
        render(canvas);
        canvas.flush();
    }

    protected abstract void render(TCanvas html);

    public ActionInvocationBuilderKnownController<? extends TController> path() {
        return util.path(controllerClass);
    }

    public <T extends IController> ActionInvocationBuilderKnownController<T> path(
            Class<T> controllerClass) {
        return util.path(controllerClass);
    }

    public <T extends IController> T go(Class<T> controllerClass) {
        return util.go(controllerClass);
    }

    public TController go() {
        return util.go(controllerClass);
    }

    public String url(ActionResult path) {
        return util.url(path);
    }

    public LString label(Class<?> clazz) {
        return labelUtil.getTypeLabel(clazz);
    }

    public LString label(Object obj) {
        return labelUtil.getTypeLabel(obj.getClass());
    }

    public LString label(Enum<?> enumMember) {
        return labelUtil.getEnumMemberLabel(enumMember);
    }

    public String resolve(LString lstr) {
        return lstr.resolve(currentLocale.getCurrentLocale());
    }
}
@@ -73,44 +73,8 @@
 eam;
-%0Aimport java.util.function.Consumer;
 %0A%0Aim
@@ -884,873 +884,148 @@
 %0A * 
-method called to render the view takes a %7B@link ByteArrayOutputStream%7D as%0A * argument (%7B@link #render(ByteArrayOutputStream)%7D). Each application is%0A * supposed to create a subclass called %7B@code ViewMvc%7D which%0A * %3Cul%3E%0A * %3Cli%3Edefines an abstract method %7B@code render(AppSpecificCanvas)%7D%3C/li%3E%0A * %3Cli%3Eimplement %7B@link #render(ByteArrayOutputStream)%7D by creating a canvas%0A * instance and invoking%0A * %7B@link #render(ByteArrayOutputStream, RiseCanvasBase, Consumer)%7D, with the%0A * consumer invoking the defined %7B@code render method%7D%0A * %3C/ul%3E%0A * %0A * Sample:%0A * %0A * %3Cpre%3E%0A * &#064;%7B@code Inject%0A * Provider%3CSampleCanvas%3E canvasProvider;%0A * %7D%0A * %0A * &#064;%7B@code Override%0A * public void render(ByteArrayOutputStream out) throws IOException %7B%0A *     render(out, canvasProvider.get(), this::render);%0A * %7D%0A * %0A * protected abstract void render(SampleCanvas html);%0A * %7D%0A * %3C/pre%3E
+type is passed as generic parameter. The class is instantiated by the DI%0A * framework (salta) and passed to %7B@link #render(RiseCanvasBase)%7D.
 %0A */

fix comment