package org.jolokia.client;

/*
 * Copyright 2009-2013 Roland Huss
 *
 * 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.
 */

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;

import org.jolokia.client.request.JolokiaRequest;
import org.jolokia.client.response.JolokiaResponse;
import org.jolokia.json.JSONArray;
import org.jolokia.json.JSONObject;
import org.jolokia.json.parser.JSONParser;
import org.jolokia.json.parser.ParseException;
import org.testng.annotations.Test;

import static org.testng.Assert.*;

/**
 * @author roland
 * @since 27.03.11
 */

public class JsonSerializationTest {

    @Test
    public void nullSerialization() {
        Object result = serialize(null);
        assertNull(result);
    }

    @Test
    public void JSONStructureSerialization() {
        JSONObject arg = new JSONObject();
        Object result = serialize(arg);
        assertEquals(arg, result);
    }

    @Test
    public void arraySerialization() {
        int[] arg = new int[] { 1,2,3 };
        Object result = serialize(arg);
        assertTrue(result instanceof JSONArray);
        JSONArray res = (JSONArray) result;
        assertEquals(res.get(0), 1L);
        assertEquals(res.size(), 3);
    }

    @Test
    public void mapSerialization() {
        Map<String, Number> arg = new HashMap<>();
        arg.put("arg", 10.0);
        Object result = serialize(arg);
        assertTrue(result instanceof JSONObject);
        JSONObject res = (JSONObject) result;
        assertEquals(res.get("arg"), new BigDecimal("10.0"));
    }

    @Test
    public void collectionSerialization() {
        Set<Boolean> arg = new HashSet<>();
        arg.add(true);
        Object result = serialize(arg);
        assertTrue(result instanceof JSONArray);
        JSONArray res = (JSONArray) result;
        assertEquals(res.size(), 1);
        assertEquals(res.get(0), true);
    }

    @Test
    public void complexSerialization() throws ParseException, IOException {
        Map<String, Object> arg = new HashMap<>();
        List<Object> inner = new ArrayList<>();
        inner.add(null);
        inner.add(new File("tmp"));
        inner.add(10);
        inner.add(42.0);
        inner.add(false);
        arg.put("first", "fcn");
        arg.put("second", inner);
        Object result = serialize(arg);
        assertTrue(result instanceof JSONObject);
        JSONObject res = (JSONObject) result;
        assertEquals(res.get("first"), "fcn");
        assertTrue(res.get("second") instanceof JSONArray);
        JSONArray arr = (JSONArray) res.get("second");
        assertEquals(arr.size(), 5);
        assertNull(arr.get(0));
        assertEquals(((JSONObject) arr.get(1)).get("name"), "tmp");
        assertEquals(arr.get(2), 10L);
        assertEquals(arr.get(3), new BigDecimal("42.0"));
        assertEquals(arr.get(4), false);
        String json = res.toJSONString();
        assertNotNull(json);
        JSONObject reparsed = new JSONParser().parse(json, JSONObject.class);
        assertNotNull(reparsed);
        assertEquals(((JSONObject) ((List<?>) reparsed.get("second")).get(1)).get("name"), "tmp");
    }

    // =====================================================================================================

    private Object serialize(Object o) {
        JolokiaRequest req = new JolokiaRequest(JolokiaOperation.VERSION,null) {
            @Override
            public List<String> getRequestParts() {
                return null;
            }

            @Override
            public <RES extends JolokiaResponse<REQ>, REQ extends JolokiaRequest> RES createResponse(JSONObject pResponse) {
                return null;
            }
        };
        return req.serializeArgumentToJson(o);
    }

}
