/**
 * Copyright (C) 2015 Red Hat, Inc.
 *
 * 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.fabric8.kubernetes.client.dsl.internal;

import java.io.IOException;

import io.fabric8.kubernetes.api.model.KubernetesResource;
import io.fabric8.kubernetes.api.model.apiextensions.v1beta1.CustomResourceDefinition;
import io.fabric8.kubernetes.client.CustomResource;
import io.fabric8.kubernetes.client.CustomResourceList;
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
import io.fabric8.kubernetes.client.dsl.MixedOperation;
import io.fabric8.kubernetes.client.dsl.Resource;
import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext;
import io.fabric8.kubernetes.internal.KubernetesDeserializer;

import io.fabric8.kubernetes.model.annotation.ApiGroup;
import io.fabric8.kubernetes.model.annotation.ApiVersion;
import org.junit.jupiter.api.Test;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.MappingJsonFactory;

import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;

public class CustomResourceOperationsImplTest {

  @ApiGroup(MyCustomResource.GROUP)
  @ApiVersion(MyCustomResource.VERSION)
  public static class MyCustomResource extends CustomResource {
    public static final String GROUP = "custom.group";
    public static final String VERSION = "v1alpha1";
  }

  public static class MyCustomResourceList extends CustomResourceList<MyCustomResource> {
  }
  
  @ApiGroup("sample.fabric8.io")
  @ApiVersion("v1")
  public static class Bar extends CustomResource {}

  /*private final CustomResourceDefinition crd = new CustomResourceDefinitionBuilder()
    .withNewMetadata()
      .withName("custom.name")
    .endMetadata()
    .withNewSpec()
      .withGroup(MyCustomResource.GROUP)
      .withVersion(MyCustomResource.VERSION)
      .withNewNames()
        .withKind("MyCustomResource")
        .withListKind("MyCustomResourceList")
        .withPlural("mycustomresources")
        .withSingular("mycustomresource")
      .endNames()
    .endSpec()
  .build();*/
  private final CustomResourceDefinition crd = CustomResourceDefinitionContext.crdFromCustomResourceType(MyCustomResource.class).build();

  @Test
  void shouldBeAbleToReturnOperationsWithoutSpecificList() {
    final MixedOperation<Bar, CustomResourceList, Resource<Bar>> operation = new DefaultKubernetesClient().customResources(Bar.class, CustomResourceList.class);
    assertNotNull(operation);
  }
  
  @Test
  public void shouldRegisterWithKubernetesDeserializer() throws IOException {
    assertForContext(new CustomResourceOperationContext()
      .withCrd(crd)
      .withType(MyCustomResource.class)
      .withListType(MyCustomResourceList.class));
  }
  
  @Test
  public void shouldWorkWithPlainCustomResourceList() throws IOException {
    assertForContext(new CustomResourceOperationContext()
      .withCrd(crd)
      .withType(MyCustomResource.class)
      .withListType(CustomResourceList.class));
  }

  @Test
  void itFallsBackOnTypeKindIfNoKindSpecifiedInContext() throws IOException {
    assertForContext(new CustomResourceOperationContext()
      .withCrdContext(new CustomResourceDefinitionContext.Builder()
      .withGroup(crd.getSpec().getGroup())
      .withVersion(crd.getSpec().getVersion())
      .withScope(crd.getSpec().getScope())
      .withName(crd.getMetadata().getName())
      .withPlural(crd.getSpec().getNames().getPlural())
      .build())
      .withType(MyCustomResource.class)
      .withListType(MyCustomResourceList.class));
  }
  
  @Test
  void canProperlyInferListType() {
    assertEquals(MyCustomResourceList.class, CustomResourceOperationsImpl.inferListType(MyCustomResource.class));
    assertEquals(FooList.class, CustomResourceOperationsImpl.inferListType(Foo.class));
    assertEquals(CustomResourceList.class, CustomResourceOperationsImpl.inferListType(Bar.class));
  }

  private void assertForContext(CustomResourceOperationContext context) throws IOException {
    // CustomResourceOperationsImpl constructor invokes KubernetesDeserializer::registerCustomKind
    new CustomResourceOperationsImpl<>(context);

    JsonFactory factory = new MappingJsonFactory();
    JsonParser parser = factory.createParser("{\n" +
      "    \"apiVersion\": \"custom.group/v1alpha1\",\n" +
      "    \"kind\": \"MyCustomResource\"\n" +
      "}");

    KubernetesDeserializer deserializer = new KubernetesDeserializer();
    KubernetesResource resource = deserializer.deserialize(parser, null);

    assertThat(resource, instanceOf(MyCustomResource.class));
    assertEquals("custom.group/v1alpha1", ((MyCustomResource) resource).getApiVersion());
  }
}

@@ -2245,509 +2245,8 @@
 %7B%7D%0A%0A
-  /*private final CustomResourceDefinition crd = new CustomResourceDefinitionBuilder()%0A    .withNewMetadata()%0A      .withName(%22custom.name%22)%0A    .endMetadata()%0A    .withNewSpec()%0A      .withGroup(MyCustomResource.GROUP)%0A      .withVersion(MyCustomResource.VERSION)%0A      .withNewNames()%0A        .withKind(%22MyCustomResource%22)%0A        .withListKind(%22MyCustomResourceList%22)%0A        .withPlural(%22mycustomresources%22)%0A        .withSingular(%22mycustomresource%22)%0A      .endNames()%0A    .endSpec()%0A  .build();*/%0A
   pr

clean-up