/*
 * 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.felix.sigil.common.runtime.io;


import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import org.osgi.framework.BundleException;
import org.osgi.framework.launch.Framework;

import org.apache.felix.sigil.common.runtime.Main;

import static org.apache.felix.sigil.common.runtime.io.Constants.OK;
import static org.apache.felix.sigil.common.runtime.io.Constants.ERROR;


/**
 * @author dave
 *
 */
public abstract class Action<I, O>
{
    private static final String ASCII = "ASCII";
    private final DataInputStream in;
    private final DataOutputStream out;


    public Action( DataInputStream in, DataOutputStream out ) throws IOException
    {
        this.in = in;
        this.out = out;
    }


    public O client() throws IOException, BundleException
    {
        return client( null );
    }


    public abstract O client( I input ) throws IOException, BundleException;


    public abstract void server( Framework fw ) throws IOException;


    protected boolean checkOk() throws IOException
    {
        int ch = readInt();
        switch ( ch )
        {
            case OK:
                return true;
            case ERROR:
                return false;
            default:
                throw new IOException( "Unexpected return code " + ch );
        }
    }


    protected void writeOk() throws IOException
    {
        writeInt( OK );
    }


    protected void writeError() throws IOException
    {
        writeInt( ERROR );
    }


    protected String readString() throws IOException
    {
        int l = in.readInt();
        byte[] buf = new byte[l];
        in.readFully( buf );
        return new String(buf, ASCII);
    }


    protected void writeString( String str ) throws IOException
    {
        byte[] buf = str.getBytes( ASCII );
        out.writeInt( buf.length );
        out.write( buf );
    }


    protected void writeInt( int i ) throws IOException
    {
        out.writeInt( i );
    }


    protected int readInt() throws IOException
    {
        return in.readInt();
    }


    protected void writeLong( long l ) throws IOException
    {        
        out.writeLong( l );
    }


    protected long readLong() throws IOException
    {
        return in.readLong();
    }

    protected void writeBoolean( boolean b ) throws IOException
    {
        out.writeBoolean( b );
    }
    
    protected boolean readBoolean() throws IOException {
        return in.readBoolean();
    }
    
    protected void flush() throws IOException
    {
        out.flush();
    }
    
    protected void log(String msg) {
        Main.log( msg );
    }
}

@@ -2411,32 +2411,111 @@
 = in.readInt();%0A
+        if ( l == -1 ) %7B%0A            return null;%0A        %7D%0A        else %7B%0A    
         byte%5B%5D b
@@ -2540,16 +2540,20 @@
         
+    
 in.readF
@@ -2565,32 +2565,36 @@
  buf );%0A        
+ 
+   
 return new Strin
@@ -2608,16 +2608,26 @@
 ASCII);%0A
+        %7D%0A
     %7D%0A%0A%0A
@@ -2688,32 +2688,120 @@
 Exception%0A    %7B%0A
+        if ( str == null ) %7B%0A            out.writeInt(-1);%0A        %7D%0A        else %7B%0A    
         byte%5B%5D b
@@ -2828,32 +2828,36 @@
 SCII );%0A        
+    
 out.writeInt( bu
@@ -2868,32 +2868,36 @@
 ngth );%0A        
+  
+  
 out.write( buf )
@@ -2894,24 +2894,34 @@
 ite( buf );%0A
+        %7D%0A
     %7D%0A%0A%0A    

Handle null string value