package org.mitallast.queue.queue;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.netty.buffer.*;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.UUID;

public class QueueMessage {

    public static final Charset defaultCharset = Charset.forName("UTF-8");
    private static final JsonFactory jsonFactory = new JsonFactory(new ObjectMapper());

    private UUID uuid;
    private QueueMessageType type;
    private ByteBuf buffer;

    public QueueMessage() {
    }

    public QueueMessage(String source) {
        setSource(source);
    }

    public QueueMessage(UUID uuid, String source) {
        setUuid(uuid);
        setSource(source);
    }

    public QueueMessage(UUID uuid, QueueMessageType type, ByteBuf buffer) {
        this.uuid = uuid;
        this.type = type;
        this.buffer = buffer;
    }

    public UUID getUuid() {
        return uuid;
    }

    public void setUuid(UUID uuid) {
        this.uuid = uuid;
    }

    public QueueMessageType getMessageType() {
        return type;
    }

    public String getMessage() {
        return buffer.toString(defaultCharset);
    }

    public void setSource(String string) {
        type = QueueMessageType.STRING;
        buffer = Unpooled.wrappedBuffer(string.getBytes(defaultCharset));
    }

    public ByteBuf getSource() {
        return Unpooled.wrappedBuffer(buffer);
    }

    public void setSource(TreeNode tree) throws IOException {
        JsonFactory jsonFactory = new JsonFactory();
        if (buffer == null) {
            buffer = Unpooled.buffer();
        } else {
            buffer.clear();
        }
        type = QueueMessageType.JSON;
        try (ByteBufOutputStream outputStream = new ByteBufOutputStream(buffer)) {
            JsonGenerator generator = jsonFactory.createGenerator(outputStream);
            generator.setCodec(new ObjectMapper());
            generator.writeTree(tree);
            generator.close();
        }
    }

    public void setSource(QueueMessageType type, ByteBuf buffer) {
        this.type = type;
        this.buffer = buffer;
    }

    @Deprecated
    public InputStream getSourceAsStream() throws IOException {
        buffer.resetReaderIndex();
        return new ByteBufInputStream(buffer);
    }

    @Deprecated
    public TreeNode getSourceAsTreeNode() throws IOException {
        JsonParser parser = jsonFactory.createParser(getSourceAsStream());
        return parser.readValueAsTree();
    }

    public void writeTo(JsonGenerator generator) throws IOException {
        generator.writeStartObject();
        if (uuid != null) {
            generator.writeStringField("uuid", uuid.toString());
        }
        if (buffer != null) {
            buffer.resetReaderIndex();
            generator.writeFieldName("message");
            if (getMessageType() == QueueMessageType.STRING) {
                generator.writeString(buffer.toString(defaultCharset));
            } else if (getMessageType() == QueueMessageType.JSON) {
                while (buffer.isReadable()) {
                    buffer.writeChar(buffer.readChar());
                }
            }
        }
        generator.writeEndObject();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        QueueMessage that = (QueueMessage) o;

        if (buffer != null ? !ByteBufUtil.equals(buffer, that.buffer) : that.buffer != null) return false;
        if (type != that.type) return false;
        if (uuid != null ? !uuid.equals(that.uuid) : that.uuid != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = uuid != null ? uuid.hashCode() : 0;
        result = 31 * result + (type != null ? type.hashCode() : 0);
        result = 31 * result + (buffer != null ? ByteBufUtil.hashCode(buffer) : 0);
        return result;
    }

    @Override
    public String toString() {
        return "QueueMessage{" +
                "uuid=" + uuid +
                ", type=" + type +
                ", buffer=" + buffer.toString(defaultCharset) +
                '}';
    }
}

@@ -159,26 +159,24 @@
 on.core.
-JsonParser
+TreeNode
 ;%0Aimport
@@ -202,73 +202,141 @@
 son.
-core.TreeNode;%0Aimport com.fasterxml.jackson.databind.ObjectMapper
+databind.ObjectMapper;%0Aimport io.netty.buffer.ByteBuf;%0Aimport io.netty.buffer.ByteBufOutputStream;%0Aimport io.netty.buffer.ByteBufUtil
 ;%0Aim
@@ -356,17 +356,24 @@
 .buffer.
-*
+Unpooled
 ;%0A%0Aimpor
@@ -399,36 +399,8 @@
 on;%0A
-import java.io.InputStream;%0A
 impo
@@ -559,96 +559,8 @@
 8%22);
-%0A    private static final JsonFactory jsonFactory = new JsonFactory(new ObjectMapper());
 %0A%0A  
@@ -2283,379 +2283,8 @@
  %7D%0A%0A
-    @Deprecated%0A    public InputStream getSourceAsStream() throws IOException %7B%0A        buffer.resetReaderIndex();%0A        return new ByteBufInputStream(buffer);%0A    %7D%0A%0A    @Deprecated%0A    public TreeNode getSourceAsTreeNode() throws IOException %7B%0A        JsonParser parser = jsonFactory.createParser(getSourceAsStream());%0A        return parser.readValueAsTree();%0A    %7D%0A%0A
     
@@ -2881,24 +2881,26 @@
     
-buffe
+generato
 r.write
-Char
+Raw
 (buf
@@ -3843,20 +3843,16 @@
         
-    
 %22uuid=%22 
@@ -3860,20 +3860,16 @@
  uuid +%0A
-    
         
@@ -3903,20 +3903,16 @@
         
-    
 %22, buffe
@@ -3951,20 +3951,16 @@
 rset) +%0A
-    
         

refactor queue message