// Java class go.issue10788.Issue10788 is a proxy for talking to a Go program.
//   gobind -lang=java issue10788
//
// File is generated by gobind. Do not edit.
package go.issue10788;

import go.Seq;

public abstract class Issue10788 {
    private Issue10788() {} // uninstantiable
    
    public interface TestInterface extends go.Seq.Object {
        public void DoSomeWork(TestStruct s);
        
        public void MultipleUnnamedParams(long p0, String p1, long p2);
        
        public static abstract class Stub implements TestInterface {
            static final String DESCRIPTOR = "go.issue10788.TestInterface";
            
            private final go.Seq.Ref ref;
            public Stub() {
                ref = go.Seq.createRef(this);
            }
            
            public go.Seq.Ref ref() { return ref; }
            
            public void call(int code, go.Seq in, go.Seq out) {
                switch (code) {
                case Proxy.CALL_DoSomeWork: {
                    TestStruct param_s;
                    param_s = new TestStruct(in.readRef());
                    this.DoSomeWork(param_s);
                    return;
                }
                case Proxy.CALL_MultipleUnnamedParams: {
                    long param_p0;
                    param_p0 = in.readInt();
                    String param_p1;
                    param_p1 = in.readString();
                    long param_p2;
                    param_p2 = in.readInt64();
                    this.MultipleUnnamedParams(param_p0, param_p1, param_p2);
                    return;
                }
                default:
                    throw new RuntimeException("unknown code: "+ code);
                }
            }
        }
        
        static final class Proxy implements TestInterface {
            static final String DESCRIPTOR = Stub.DESCRIPTOR;
        
            private go.Seq.Ref ref;
        
            Proxy(go.Seq.Ref ref) { this.ref = ref; }
        
            public go.Seq.Ref ref() { return ref; }
        
            public void call(int code, go.Seq in, go.Seq out) {
                throw new RuntimeException("cycle: cannot call proxy");
            }
        
            public void DoSomeWork(TestStruct s) {
                go.Seq _in = null;
                go.Seq _out = null;
                _in = new go.Seq();
                _in.writeRef(ref);
                _in.writeRef(s.ref());
                Seq.send(DESCRIPTOR, CALL_DoSomeWork, _in, _out);
            }
            
            public void MultipleUnnamedParams(long p0, String p1, long p2) {
                go.Seq _in = null;
                go.Seq _out = null;
                _in = new go.Seq();
                _in.writeRef(ref);
                _in.writeInt(p0);
                _in.writeString(p1);
                _in.writeInt64(p2);
                Seq.send(DESCRIPTOR, CALL_MultipleUnnamedParams, _in, _out);
            }
            
            static final int CALL_DoSomeWork = 0x10a;
            static final int CALL_MultipleUnnamedParams = 0x20a;
        }
    }
    
    public static final class TestStruct implements go.Seq.Object {
        private static final String DESCRIPTOR = "go.issue10788.TestStruct";
        private static final int FIELD_Value_GET = 0x00f;
        private static final int FIELD_Value_SET = 0x01f;
        
        private go.Seq.Ref ref;
        
        private TestStruct(go.Seq.Ref ref) { this.ref = ref; }
        
        public go.Seq.Ref ref() { return ref; }
        
        public void call(int code, go.Seq in, go.Seq out) {
            throw new RuntimeException("internal error: cycle: cannot call concrete proxy");
        }
        
        public String getValue() {
            Seq in = new Seq();
            Seq out = new Seq();
            in.writeRef(ref);
            Seq.send(DESCRIPTOR, FIELD_Value_GET, in, out);
            return out.readString();
        }
        
        public void setValue(String v) {
            Seq in = new Seq();
            in.writeRef(ref);
            in.writeString(v);
            Seq.send(DESCRIPTOR, FIELD_Value_SET, in, null);
        }
        
        @Override public boolean equals(Object o) {
            if (o == null || !(o instanceof TestStruct)) {
                return false;
            }
            TestStruct that = (TestStruct)o;
            String thisValue = getValue();
            String thatValue = that.getValue();
            if (thisValue == null) {
                if (thatValue != null) {
                    return false;
                }
            } else if (!thisValue.equals(thatValue)) {
                return false;
            }
            return true;
        }
        
        @Override public int hashCode() {
            return java.util.Arrays.hashCode(new Object[] {getValue()});
        }
        
        @Override public String toString() {
            StringBuilder b = new StringBuilder();
            b.append("TestStruct").append("{");
            b.append("Value:").append(getValue()).append(",");
            return b.append("}").toString();
        }
        
    }
    
    private static final String DESCRIPTOR = "issue10788";
}
