/*
 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package com.apple.jobjc;

import com.apple.jobjc.Coder.IDCoder;
import com.apple.jobjc.Coder.NSClassCoder;
import com.apple.jobjc.Coder.PrimitivePointerCoder;
import com.apple.jobjc.Coder.SELCoder;
import com.apple.jobjc.Coder.StructCoder;


public abstract class Invoke {
    public abstract void invoke(NativeArgumentBuffer argBuf);
    public abstract void invoke(NativeArgumentBuffer buffer, Struct retvalStruct);

    //

    public static final class FunCall extends Invoke{
        static native void invoke(long cifPtr, long fxnPtr, long retValPtr, long argsPtr);

        final long fxnPtr;
        final CIF cif;

        FunCall(long fxnPtr, CIF cif) {
            this.fxnPtr = fxnPtr;
            this.cif = cif;
        }

        public FunCall(final JObjCRuntime runtime, final String name, final Coder returnCoder, final Coder ... argCoders) {
            this(Function.getFxnPtr(name), CIF.createCIFFor(runtime.getThreadLocalState(), returnCoder, argCoders));
        }

        public FunCall(final MacOSXFramework framework, final String name, final Coder returnCoder, final Coder ... argCoders) {
            this(Function.getFxnPtr(name, framework), CIF.createCIFFor(framework.getRuntime().getThreadLocalState(), returnCoder, argCoders));
        }

        public void init(final NativeArgumentBuffer argBuf) {
            argBuf.reset();
        }

        @Override public void invoke(final NativeArgumentBuffer argBuf) {
            invoke(argBuf, argBuf.retValPtr);
        }

        @Override public void invoke(final NativeArgumentBuffer buffer, final Struct retvalStruct) {
            invoke(buffer, retvalStruct.raw.bufferPtr);
        }

        void invoke(final NativeArgumentBuffer argBuf, final long retValPtr) {
            invoke(cif.cif.bufferPtr, fxnPtr, retValPtr, argBuf.buffer.bufferPtr);
        }
    }

    public static final class MsgSend extends Invoke{
        static{ System.load("/usr/lib/libobjc.dylib"); }

        private static final long OBJC_MSG_SEND_FXN_PTR = new Function("objc_msgSend").fxnPtr;
        private static final long OBJC_MSG_SEND_FPRET_FXN_PTR = new Function("objc_msgSend_fpret").fxnPtr;
        private static final long OBJC_MSG_SEND_STRET_FXN_PTR = new Function("objc_msgSend_stret").fxnPtr;

        final FunCall funCall;
        final long selPtr;

        public MsgSend(final JObjCRuntime runtime, final String name, final Coder returnCoder, final Coder ... argCoders) {
            this.funCall = new FunCall(getMsgSendFxnPtr(returnCoder),
                    CIF.createCIFFor(runtime.getThreadLocalState(), returnCoder, getSelCoders(argCoders)));
            this.selPtr = SEL.getSelectorPtr(name);
        }

        public void init(final NativeArgumentBuffer nativeBuffer, final ID obj) {
            funCall.init(nativeBuffer);
            IDCoder.INST.push(nativeBuffer, obj);
            PrimitivePointerCoder.INST.push(nativeBuffer.runtime, nativeBuffer, selPtr);
        }

        @Override public void invoke(final NativeArgumentBuffer argBuf) {
            funCall.invoke(argBuf);
        }

        @Override public void invoke(final NativeArgumentBuffer buffer, final Struct retvalStruct) {
            funCall.invoke(buffer, retvalStruct);
        }

        // support

        static Coder[] getSelCoders(final Coder[] argCoders) {
            final Coder[] selArgCoders = new Coder[argCoders.length + 2];
            selArgCoders[0] = IDCoder.INST;
            selArgCoders[1] = SELCoder.INST;
            for (int i = 0; i < argCoders.length; i++)
                selArgCoders[i + 2] = argCoders[i];
            return selArgCoders;
        }

        static long getMsgSendFxnPtr(final Coder returnCoder) {
            if(returnCoder instanceof StructCoder){
                StructCoder scoder = (StructCoder) returnCoder;

                switch(JObjCRuntime.ARCH){
                case ppc:
                    return OBJC_MSG_SEND_STRET_FXN_PTR;
                case i386:
                    switch(scoder.sizeof){
                    case 1: case 2: case 4: case 8:
                        return OBJC_MSG_SEND_FXN_PTR;
                    }
                    return OBJC_MSG_SEND_STRET_FXN_PTR;
                case x86_64:
                    if(scoder.sizeof > 16)
                        return OBJC_MSG_SEND_STRET_FXN_PTR;
                    else
                        return OBJC_MSG_SEND_FXN_PTR;
                default:
                    throw new RuntimeException();
                }
            }

            final int typeCode = returnCoder.getTypeCode();

            switch(JObjCRuntime.ARCH){
            case ppc:
                return OBJC_MSG_SEND_FXN_PTR;
            case i386:
                switch(typeCode) {
                case Coder.FFI_FLOAT: case Coder.FFI_DOUBLE: case Coder.FFI_LONGDOUBLE:
                    return OBJC_MSG_SEND_FPRET_FXN_PTR;
                }
                return OBJC_MSG_SEND_FXN_PTR;
            case x86_64:
                if(typeCode == Coder.FFI_LONGDOUBLE)
                    return OBJC_MSG_SEND_FPRET_FXN_PTR;
                return OBJC_MSG_SEND_FXN_PTR;
            default:
                throw new RuntimeException();
            }
        }
    }

    public static final class MsgSendSuper extends Invoke{
        static{ System.load("/usr/lib/libobjc.dylib"); }

        private static final long OBJC_MSG_SEND_SUPER_FXN_PTR = new Function("objc_msgSendSuper").fxnPtr;
        private static final long OBJC_MSG_SEND_SUPER_STRET_FXN_PTR = new Function("objc_msgSendSuper_stret").fxnPtr;

        final FunCall funCall;
        final long selPtr;

        public MsgSendSuper(final JObjCRuntime runtime, final String name, final Coder returnCoder, final Coder ... argCoders) {
            this.funCall = new FunCall(getMsgSendSuperFxnPtr(returnCoder),
                    CIF.createCIFFor(runtime.getThreadLocalState(), returnCoder, getSuperSelCoders(argCoders)));
            this.selPtr = SEL.getSelectorPtr(name);
        }

        public void init(final NativeArgumentBuffer argBuf, final ID obj, final NSClass cls) {
            funCall.init(argBuf);

            // Instead of mallocing a struct, or keeping another thread local,
            // let's write objc_super out to the argbuf, and then point an argument
            // to the data.

            final long valPtr = argBuf.argValuesPtr;
            final int ptrLen = JObjCRuntime.PTR_LEN;

            IDCoder     .INST.push(argBuf.runtime, valPtr,          obj);
            NSClassCoder.INST.push(argBuf.runtime, valPtr + ptrLen, cls);
            argBuf.argValuesPtr += ptrLen + ptrLen;

            PrimitivePointerCoder.INST.push(argBuf.runtime, argBuf, valPtr);
            PrimitivePointerCoder.INST.push(argBuf.runtime, argBuf, selPtr);
        }

        @Override public void invoke(final NativeArgumentBuffer argBuf) {
            funCall.invoke(argBuf);
        }

        @Override public void invoke(final NativeArgumentBuffer buffer, final Struct retvalStruct) {
            funCall.invoke(buffer, retvalStruct);
        }

        //

        private final static StructCoder objc_super_coder = new StructCoder(JObjCRuntime.PTR_LEN*2, IDCoder.INST, NSClassCoder.INST){
            @Override protected Struct newInstance(JObjCRuntime runtime) { return null; }};

        static Coder[] getSuperSelCoders(final Coder[] argCoders) {
            final Coder[] selArgCoders = new Coder[argCoders.length + 2];
            selArgCoders[0] = objc_super_coder;
            selArgCoders[1] = SELCoder.INST;
            for (int i = 0; i < argCoders.length; i++)
                selArgCoders[i + 2] = argCoders[i];
            return selArgCoders;
        }

        static long getMsgSendSuperFxnPtr(final Coder returnCoder){
            long normal = MsgSend.getMsgSendFxnPtr(returnCoder);
            if(normal == MsgSend.OBJC_MSG_SEND_STRET_FXN_PTR)
                return OBJC_MSG_SEND_SUPER_STRET_FXN_PTR;
            else
                return OBJC_MSG_SEND_SUPER_FXN_PTR;
        }
    }
}
