package com.livefyre.protobuf.rpc;

import com.googlecode.protobuf.socketrpc.SocketRpcProtos;

public class Exceptions {

    // base exception
    static class ProtoRpcException extends RuntimeException {
        ProtoRpcException(String message) {
            super(message);
        }
    }

    // channel exceptions
    static class TimeoutException extends ProtoRpcException {
        TimeoutException(String message) {
            super(message);
        }
    }

    static class ChannelClosedException extends ProtoRpcException {
        ChannelClosedException(String message) {
            super(message);
        }
    }

    static class BadResponseProtoError extends ProtoRpcException {
        BadResponseProtoError(String message) {
            super(message);
        }
    }

    // server exceptions
    static class InvalidRequestProtoException extends ProtoRpcException {
        InvalidRequestProtoException(String message) { super(message); }
    }
    static class RpcError extends ProtoRpcException {
        RpcError(String message) {
            super(message);
        }
    }

    static class RpcFailedError extends ProtoRpcException {
        RpcFailedError(String message) {
            super(message);
        }
    }

    static class BadRequestDataError extends ProtoRpcException {
        BadRequestDataError(String message) {
            super(message);
        }
    }

    static class BadRequestProtoError extends ProtoRpcException {
        BadRequestProtoError(String message) {
            super(message);
        }
    }

    static class ServiceNotFoundError extends ProtoRpcException {
        ServiceNotFoundError(String message) {
            super(message);
        }
    }

    static class MethodNotFoundError extends ProtoRpcException {
        MethodNotFoundError(String message) {
            super(message);
        }
    }

    public static ProtoRpcException getFrom(Controller controller) {
        SocketRpcProtos.ErrorReason error_code = controller.rpcError();
        // client errors
        if (error_code == null) {
            if (controller.channelError() == Channel.Errors.TIMEOUT) {
                return new TimeoutException(controller.errorText());
            }
            if (controller.channelError() == Channel.Errors.CHANNEL_CLOSED) {
                return new ChannelClosedException(controller.errorText());
            }
            if (controller.channelError() == Channel.Errors.INVALID_RESPONSE) {
                return new BadResponseProtoError(controller.errorText());
            }
            return new RpcError("Unknown Error");
        }
        // server errors
        switch (error_code) {
            case INVALID_REQUEST_PROTO:
                return new InvalidRequestProtoException(controller.errorText());
            case RPC_FAILED:
                return new RpcFailedError(controller.errorText());
            case BAD_REQUEST_DATA:
                return new BadRequestDataError(controller.errorText());
            case BAD_REQUEST_PROTO:
                return new BadRequestProtoError(controller.errorText());
            case SERVICE_NOT_FOUND:
                return new ServiceNotFoundError(controller.errorText());
            case METHOD_NOT_FOUND:
                return new MethodNotFoundError(controller.errorText());
            default:
                return new RpcError(controller.errorText());
        }
    }

    public static ProtoRpcException getCause(Exception e) {
        Throwable t = e.getCause();
        if (t instanceof TimeoutException) {
            return (TimeoutException) t;
        }
        if (t instanceof ChannelClosedException) {
            return (ChannelClosedException) t;
        }
        if (t instanceof BadResponseProtoError) {
            return (BadResponseProtoError) t;
        }
        if (t instanceof  InvalidRequestProtoException) {
            return (InvalidRequestProtoException) t;
        }
        if (t instanceof RpcError) {
            return (RpcError) t;
        }
        if (t instanceof RpcFailedError) {
            return (RpcFailedError) t;
        }
        if (t instanceof BadRequestDataError) {
            return (BadRequestDataError) t;
        }
        if (t instanceof  BadRequestProtoError) {
            return (BadRequestProtoError) t;
        }
        if (t instanceof ServiceNotFoundError) {
            return (ServiceNotFoundError) t;
        }
        if (t instanceof MethodNotFoundError) {
            return (MethodNotFoundError) t;
        }
        return (ProtoRpcException) e;
    }

}

@@ -137,24 +137,31 @@
 ception%0A    
+public 
 static class
@@ -214,16 +214,23 @@
         
+public 
 ProtoRpc
@@ -324,32 +324,39 @@
  exceptions%0A    
+public 
 static class Tim
@@ -405,16 +405,23 @@
         
+public 
 TimeoutE
@@ -488,32 +488,39 @@
    %7D%0A    %7D%0A%0A    
+public 
 static class Cha
@@ -575,16 +575,23 @@
         
+public 
 ChannelC
@@ -664,32 +664,39 @@
    %7D%0A    %7D%0A%0A    
+public 
 static class Bad
@@ -746,24 +746,31 @@
 n %7B%0A        
+public 
 BadResponseP
@@ -867,24 +867,31 @@
 eptions%0A    
+public 
 static class
@@ -956,16 +956,23 @@
         
+public 
 InvalidR
@@ -1034,24 +1034,31 @@
 %7D%0A    %7D%0A    
+public 
 static class
@@ -1103,16 +1103,23 @@
         
+public 
 RpcError
@@ -1178,32 +1178,39 @@
    %7D%0A    %7D%0A%0A    
+public 
 static class Rpc
@@ -1257,16 +1257,23 @@
         
+public 
 RpcFaile
@@ -1338,32 +1338,39 @@
    %7D%0A    %7D%0A%0A    
+public 
 static class Bad
@@ -1414,32 +1414,39 @@
 ption %7B%0A        
+public 
 BadRequestDataEr
@@ -1508,32 +1508,39 @@
    %7D%0A    %7D%0A%0A    
+public 
 static class Bad
@@ -1593,16 +1593,23 @@
         
+public 
 BadReque
@@ -1680,32 +1680,39 @@
    %7D%0A    %7D%0A%0A    
+public 
 static class Ser
@@ -1765,16 +1765,23 @@
         
+public 
 ServiceN
@@ -1860,16 +1860,23 @@
  %7D%0A%0A    
+public 
 static c
@@ -1936,16 +1936,23 @@
         
+public 
 MethodNo

access modifiers