/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.servicecomb.it.testcase.base;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;

import org.apache.servicecomb.foundation.common.Holder;
import org.apache.servicecomb.it.Consumers;
import org.apache.servicecomb.it.schema.Generic;
import org.apache.servicecomb.it.schema.User;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Assertions;
import org.springframework.http.HttpStatus;

public class TestGeneric {
  interface GenericIntf {
    Holder<User> holderUser(Holder<User> input);

    Generic<User> genericUser(Generic<User> input);

    Generic<Long> genericLong(Generic<Long> input);

    Generic<Date> genericDate(Generic<Date> input);

    Generic<HttpStatus> genericEnum(Generic<HttpStatus> input);

    Generic<Generic<User>> genericGenericUser(Generic<Generic<User>> input);

    Generic<Map<String, String>> genericMap(Generic<Map<String, String>> mapGeneric);

    Generic<Map<String, List<String>>> genericMapList(Generic<Map<String, List<String>>> mapListGeneric);

    Generic<Map<String, List<User>>> genericMapListUser(Generic<Map<String, List<User>>> mapListUserGeneric);

    List<List<String>> genericNestedListString(List<List<String>> nestedListString);

    List<List<User>> genericNestedListUser(List<List<User>> nestedListUser);
  }

  private static Consumers<GenericIntf> consumers = new Consumers<>("generic", GenericIntf.class);

  private String expectUserStr = "{\"name\":\"nameA\",\"age\":100,\"index\":0,\"names\":null}";

  private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);

  @Test
  public void testHolderUser_intf() {
    Holder<User> holder = new Holder<>(new User());
    Holder<User> result = consumers.getIntf().holderUser(holder);
    Assertions.assertEquals(result.value.jsonString(), expectUserStr);
  }

  @Test
  public void testHolderUser_rt() {
    Holder<User> holder = new Holder<>(new User());
    @SuppressWarnings("unchecked")
    Holder<User> result = consumers.getSCBRestTemplate().postForObject("/holderUser", holder, Holder.class);
    Assertions.assertEquals(result.value.jsonString(), expectUserStr);
  }

  @Test
  public void testGenericUser_intf() {
    Generic<User> generic = new Generic<>();
    generic.value = new User();

    Generic<User> result = consumers.getIntf().genericUser(generic);
    Assertions.assertEquals(result.value.jsonString(), expectUserStr);
  }

  @Test
  public void testGenericUser_rt() {
    Generic<User> generic = new Generic<>();
    generic.value = new User();
    @SuppressWarnings("unchecked")
    Generic<User> result = consumers.getSCBRestTemplate().postForObject("/genericUser", generic, Generic.class);
    Assertions.assertEquals(result.value.jsonString(), expectUserStr);
  }

  @Test
  public void testGenericLong_intf() {
    Generic<Long> generic = new Generic<>();
    generic.value = 100L;
    Generic<Long> result = consumers.getIntf().genericLong(generic);
    Assertions.assertEquals(Long.class, result.value.getClass());
    Assertions.assertEquals(100L, (long) result.value);
  }

  @Test
  public void testGenericLong_rt() {
    Generic<Long> generic = new Generic<>();
    generic.value = 100L;
    @SuppressWarnings("unchecked")
    Generic<Long> result = consumers.getSCBRestTemplate().postForObject("/genericLong", generic, Generic.class);
    Assertions.assertEquals(Long.class, result.value.getClass());
    Assertions.assertEquals(100L, (long) result.value);
  }

  @Test
  public void testGenericDate_intf() {
    Generic<Date> generic = new Generic<>();
    generic.value = new Date(1001);
    Generic<Date> result = consumers.getIntf().genericDate(generic);
    Assertions.assertEquals(result.value.getClass(), Date.class);
    simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
    Assertions.assertEquals("1970-01-01T00:00:01.001Z", simpleDateFormat.format(result.value));
  }

  @Test
  public void testGenericDate_rt() {
    Generic<Date> generic = new Generic<>();
    generic.value = new Date(1001);
    @SuppressWarnings("unchecked")
    Generic<Date> result = consumers.getSCBRestTemplate().postForObject("/genericDate", generic, Generic.class);
    Assertions.assertEquals(result.value.getClass(), Date.class);
    simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
    Assertions.assertEquals("1970-01-01T00:00:01.001Z", simpleDateFormat.format(result.value));
  }

  @Test
  public void testGenericEnum_intf() {
    Generic<HttpStatus> generic = new Generic<>();
    generic.value = HttpStatus.OK;

    Generic<HttpStatus> result = consumers.getIntf().genericEnum(generic);
    Assertions.assertEquals(HttpStatus.class, result.value.getClass());
    Assertions.assertEquals(HttpStatus.OK, result.value);
  }

  @Test
  public void testGenericEnum_rt() {
    Generic<HttpStatus> generic = new Generic<>();
    generic.value = HttpStatus.OK;
    @SuppressWarnings("unchecked")
    Generic<HttpStatus> result = consumers.getSCBRestTemplate().postForObject("/genericEnum", generic, Generic.class);
    Assertions.assertEquals(HttpStatus.class, result.value.getClass());
    Assertions.assertEquals(HttpStatus.OK, result.value);
  }

  @Test
  public void testGenericGenericUser_intf() {
    Generic<Generic<User>> generic = new Generic<>();
    generic.value = new Generic<>();
    generic.value.value = new User();

    Generic<Generic<User>> result = consumers.getIntf().genericGenericUser(generic);
    Assertions.assertEquals(result.value.value.jsonString(), expectUserStr);
  }

  @Test
  public void testGenericGenericUser_rt() {
    Generic<Generic<User>> generic = new Generic<>();
    generic.value = new Generic<>();
    generic.value.value = new User();
    @SuppressWarnings("unchecked")
    Generic<Generic<User>> result = consumers.getSCBRestTemplate()
        .postForObject("/genericGenericUser", generic, Generic.class);
    Assertions.assertEquals(result.value.value.jsonString(), expectUserStr);
  }

  @Test
  public void testGenericMap_intf() {
    Generic<Map<String, String>> mapGeneric = new Generic<>();
    Map<String, String> map = new HashMap<>();
    map.put("test", "hello");
    mapGeneric.value = map;
    Generic<Map<String, String>> result = consumers.getIntf().genericMap(mapGeneric);
    String test = result.value.get("test");
    Assertions.assertEquals(test, "hello");
  }

  @Test
  public void testGenericMap_rt() {
    Generic<Map<String, String>> mapGeneric = new Generic<>();
    Map<String, String> map = new HashMap<>();
    map.put("test", "hello");
    mapGeneric.value = map;
    @SuppressWarnings("unchecked")
    Generic<Map<String, String>> result = consumers.getSCBRestTemplate()
        .postForObject("/genericMap", mapGeneric, Generic.class);
    String test = result.value.get("test");
    Assertions.assertEquals(test, "hello");
  }

  @Test
  public void testGenericListMap_intf() {
    Generic<Map<String, List<String>>> mapListGeneric = new Generic<>();
    Map<String, List<String>> map = new HashMap<>();
    List<String> list = new ArrayList<>();
    list.add("hello");
    map.put("test", list);
    mapListGeneric.value = map;
    Generic<Map<String, List<String>>> result = consumers.getIntf().genericMapList(mapListGeneric);
    String test = result.value.get("test").get(0);
    Assertions.assertEquals(test, "hello");
  }

  @Test
  public void testGenericListMap_rt() {
    Generic<Map<String, List<String>>> mapListGeneric = new Generic<>();
    Map<String, List<String>> map = new HashMap<>();
    List<String> list = new ArrayList<>();
    list.add("hello");
    map.put("test", list);
    mapListGeneric.value = map;
    @SuppressWarnings("unchecked")
    Generic<Map<String, List<String>>> result = consumers.getSCBRestTemplate()
        .postForObject("/genericMapList", mapListGeneric, Generic.class);
    String test = result.value.get("test").get(0);
    Assertions.assertEquals(test, "hello");
  }

  @Test
  public void testGenericListUserMap_intf() {
    Generic<Map<String, List<User>>> mapListUserGeneric = new Generic<>();
    Map<String, List<User>> map = new HashMap<>();
    List<User> list = new ArrayList<>();
    list.add(new User());
    map.put("test", list);
    mapListUserGeneric.value = map;
    Generic<Map<String, List<User>>> result = consumers.getIntf().genericMapListUser(mapListUserGeneric);
    String test = result.value.get("test").get(0).jsonString();
    Assertions.assertEquals(test, expectUserStr);
  }

  @Test
  public void testGenericListUserMap_rt() {
    Generic<Map<String, List<User>>> mapListUserGeneric = new Generic<>();
    Map<String, List<User>> map = new HashMap<>();
    List<User> list = new ArrayList<>();
    list.add(new User());
    map.put("test", list);
    mapListUserGeneric.value = map;
    @SuppressWarnings("unchecked")
    Generic<Map<String, List<User>>> result = consumers.getSCBRestTemplate()
        .postForObject("/genericMapListUser", mapListUserGeneric, Generic.class);
    String test = result.value.get("test").get(0).jsonString();
    Assertions.assertEquals(test, expectUserStr);
  }

  @Test
  public void testGenericNestedListString_intfAndRt() {
    ArrayList<List<String>> nestedListString = new ArrayList<>();
    nestedListString.add(Arrays.asList("abc", "def"));
    nestedListString.add(Arrays.asList("ghi", "jkl"));

    List<List<String>> response = consumers.getIntf().genericNestedListString(nestedListString);
    Assertions.assertEquals(2, response.size());
    MatcherAssert.assertThat(response.get(0), Matchers.contains("abc", "def"));
    MatcherAssert.assertThat(response.get(1), Matchers.contains("ghi", "jkl"));

    @SuppressWarnings("unchecked")
    List<List<String>> response2 = consumers.getSCBRestTemplate()
        .postForObject("/genericNestedListString", nestedListString, List.class);
    Assertions.assertEquals(2, response2.size());
    MatcherAssert.assertThat(response2.get(0), Matchers.contains("abc", "def"));
    MatcherAssert.assertThat(response2.get(1), Matchers.contains("ghi", "jkl"));
  }

  @Test
  public void testGenericNestedListUser_intfAndRt() {
    User user1 = new User();
    user1.setAge(1);
    user1.setIndex(1);
    user1.setName("abc");
    user1.setNames(new String[] {"1", "2", "3"});
    User user2 = new User();
    user2.setAge(2);
    user2.setIndex(2);
    user2.setName("def");
    user2.setNames(new String[] {"4", "5"});
    User user3 = new User();
    user3.setAge(3);
    user3.setIndex(3);
    user3.setName("ghi");
    user3.setNames(new String[] {"6", "7"});
    User user4 = new User();
    user4.setAge(4);
    user4.setIndex(4);
    user4.setName("jkl");
    user4.setNames(new String[] {"8", "9", "10"});
    ArrayList<List<User>> nestedListUser = new ArrayList<>();
    nestedListUser.add(Arrays.asList(user1, user2));
    nestedListUser.add(Arrays.asList(user3, user4));

    List<List<User>> response = consumers.getIntf().genericNestedListUser(nestedListUser);
    Assertions.assertEquals(2, response.size());
    MatcherAssert.assertThat(response.get(0), Matchers.contains(user1, user2));
    MatcherAssert.assertThat(response.get(1), Matchers.contains(user3, user4));

    @SuppressWarnings("unchecked")
    List<List<User>> response2 = consumers.getSCBRestTemplate()
        .postForObject("/genericNestedListUser", nestedListUser, List.class);
    Assertions.assertEquals(2, response2.size());
    MatcherAssert.assertThat(response2.get(0), Matchers.contains(user1, user2));
    MatcherAssert.assertThat(response2.get(1), Matchers.contains(user3, user4));
  }
}
