/**
 * 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.netbeans.html.ko4j;

import net.java.html.json.Model;
import net.java.html.json.OnReceive;
import org.netbeans.html.boot.spi.Fn;
import org.netbeans.html.context.spi.Contexts;
import org.netbeans.html.context.spi.Contexts.Provider;
import org.netbeans.html.json.spi.Technology;
import org.netbeans.html.json.spi.Transfer;
import org.netbeans.html.json.spi.WSTransfer;
import org.openide.util.lookup.ServiceProvider;

/** Support for <a href="http://knockoutjs.com">knockout.js</a>
 * and its Java binding via {@link Model model classes}.
 * Registers {@link Provider}, so {@link java.util.ServiceLoader} can find it.
 * The provider registers following technologies:
 * <ul>
 * <li><b>ko4j</b> - bindings for <a href="http://knockoutjs.com">knockout.js</a>
 *   and the classes generated by the {@link Model} annotation.
 * </li>
 * <li><b>xhr</b> - <a href="http://www.w3.org/TR/XMLHttpRequest/">XMLHttpRequest</a>
 *   based implementation for <em>REST</em> calls 
 *   (<b>GET</b>, <b>PUT</b>, <b>POST</b>, <b>DELETE</b> methods) 
 *   for {@link OnReceive} annotation.
 * </li>
 * <li><b>websocket</b> - 
 *   native browser <a href="http://www.w3.org/TR/websockets/">websockets</a>
 *   based implementation for {@link OnReceive} annotation and its <b>WebSocket</b>
 *   subprotocol.
 * </li>
 * </ul>
 *
 * @author Jaroslav Tulach
 * @since 0.7
 */
@ServiceProvider(service = Provider.class)
public final class KO4J implements Provider {
    private KOTech ko4j;
    private KOTransfer trans;
    private KOSockets socks;
    
    public KO4J() {
        this(null);
    }

    @Deprecated
    public KO4J(Fn.Presenter presenter) {
    }
    
    /** Return instance of the knockout.js for Java technology.
     * @return non-null instance
     */
    public Technology knockout() {
        if (ko4j == null) {
            ko4j = new KOTech();
        }
        return ko4j;
    }
    
    /** Browser based implementation of transfer interface. Uses
     * browser method to convert string to JSON.
     * 
     * @return non-null instance
     */
    public Transfer transfer() {
        if (trans == null) {
            trans = new KOTransfer();
        }
        return trans;
    }
    
    /** Returns browser based implementation of websocket transfer.
     * If available (for example JavaFX WebView on JDK7 does not have
     * this implementation).
     * 
     * @return an instance or <code>null</code>, if there is no
     *   <code>WebSocket</code> object in the browser
     */
    public WSTransfer<?> websockets() {
        if (!KOSockets.areWebSocketsSupported()) {
            return null;
        }
        if (socks == null) {
            socks = new KOSockets();
        }
        return socks;
    }

    /** Registers technologies at position 100:
     * <ul>
     *   <li>{@link #knockout()}</li>
     *   <li>{@link #transfer()}</li>
     *   <li>{@link #websockets()()} - if browser supports web sockets</li>
     * </ul>
     * @param context the context to register to
     * @param requestor the class requesting the registration
     */
    @Override
    public void fillContext(Contexts.Builder context, Class<?> requestor) {
        context.register(Technology.class, knockout(), 100);
        context.register(Transfer.class, transfer(), 100);
        context.register(WSTransfer.class, websockets(), 100);
    }
    
}
