/**
 * Copyright (C) 2013 Motown.IO (info@motown.io)
 *
 * Licensed 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 io.motown.ocpp.websocketjson.wamp;

import io.motown.ocpp.websocketjson.schema.MessageProcUri;

import java.io.IOException;
import java.io.Reader;

/**
 * Wamp specific message parser
 */
public class WampMessageParser {

    public WampMessageParser() {
    }

    /**
     * Parses a CALL, RESULT, or ERROR message and constructs a WampMessage
     * @param reader containing the message
     * @return WampMessage
     * @throws IOException in case the message could not be read
     * @throws IllegalArgumentException in case an unknown wamp messageType is encountered
     */
    public WampMessage parseMessage(Reader reader) throws IOException {
        String rawMessage = this.convertToString(reader);

        //In case a payload is present, it always is the last part of the message
        int payloadStart = rawMessage.indexOf("{");
        String payload = payloadStart > 0 ? rawMessage.substring(payloadStart) : null;
        String metaData = payloadStart > 0 ? rawMessage.substring(0, payloadStart) : rawMessage;
        String[] metaDataParts = metaData.split(",");

        int messageType = Integer.parseInt(removeQuotesAndTrim(metaDataParts[0]));
        String callId = removeQuotes(removeQuotesAndTrim(metaDataParts[1]));

        WampMessage wampMessage;
        switch (messageType) {
            case WampMessage.CALL:
                MessageProcUri procUri = MessageProcUri.fromValue(removeQuotesAndTrim(metaDataParts[2]));
                wampMessage = new WampMessage(messageType, callId, procUri, payload);
                break;
            case WampMessage.CALL_RESULT:
                wampMessage = new WampMessage(messageType, callId, payload);
                break;
            case WampMessage.CALL_ERROR:
                String errorCode = removeQuotes(metaDataParts[2]);
                String errorDescription = removeQuotes(metaDataParts[3]);
                String errorDetails = removeQuotes(metaDataParts[4]);
                wampMessage = new WampMessage(messageType, callId, errorCode, errorDescription, errorDetails);
                break;
            default:
                throw new IllegalArgumentException(String.format("Unknown WAMP messageType: %s", messageType));
        }
        return wampMessage;
    }

    /**
     * Constructs a String by reading the characters from the Reader
     * @param reader Reader to read from
     * @return String containing the message
     * @throws IOException in case of read failure
     */
    private String convertToString(Reader reader) throws IOException {
        StringBuilder stringBuilder = new StringBuilder();
        int numChars;
        char[] chars = new char[50];
        do {
            numChars = reader.read(chars, 0, chars.length);
            if (numChars > 0) {
                stringBuilder.append(chars, 0, numChars);
            }
        } while (numChars != -1);

        String result = stringBuilder.toString();
        //Remove any leading or trailing spaces
        result = result.trim();
        //Strip off the leading '[' and trailing ']' characters
        return result.substring(1,result.length()-1);
    }

    /**
     * Removes all single and double quotes from the given String.
     * @param toReplace String to replace the quotes from
     * @return String without quotes
     */
    private String removeQuotes(String toReplace) {
        String noQuotes = toReplace.replaceAll("\"", "");
        noQuotes = noQuotes.replaceAll("'", "");
        return noQuotes;
    }

    /**
     * Removes leading and trailing spaces next to the removal of quotes {@link #removeQuotes(String)}
     * @param message the message to trim.
     * @return String free of quotes and leading/trailing spaces
     */
    private String removeQuotesAndTrim(String message) {
        return removeQuotes(message).trim();
    }

}

@@ -842,16 +842,68 @@
 rser %7B%0A%0A
+    private WampMessageHandler wampMessageHandler;%0A%0A
     publ
@@ -1010,32 +1010,84 @@
 s a WampMessage%0A
+     * @param chargingStationId sending the message%0A
      * @param re
@@ -1341,16 +1341,53 @@
 Message(
+ChargingStationId chargingStationId, 
 Reader r
@@ -1471,16 +1471,81 @@
 reader);
+%0A        String trimmedMessage = this.removeBrackets(rawMessage);
 %0A%0A      
@@ -1647,19 +1647,23 @@
 Start = 
-raw
+trimmed
 Message.
@@ -1712,35 +1712,39 @@
 loadStart %3E 0 ? 
-raw
+trimmed
 Message.substrin
@@ -1812,19 +1812,23 @@
 t %3E 0 ? 
-raw
+trimmed
 Message.
@@ -1856,19 +1856,23 @@
 tart) : 
-raw
+trimmed
 Message;
@@ -3743,23 +3743,14 @@
     
-String result =
+return
  str
@@ -3768,24 +3768,86 @@
 toString();%0A
+    %7D%0A%0A    private String removeBrackets(String wampString) %7B%0A
         //Re
@@ -3890,16 +3890,23 @@
         
+String 
 result =
@@ -3906,22 +3906,26 @@
 esult = 
-result
+wampString
 .trim();
@@ -4023,16 +4023,17 @@
 tring(1,
+ 
 result.l
@@ -4039,17 +4039,19 @@
 length()
--
+ - 
 1);%0A    

Refactor WAMP message conversion