/*
 * Copyright (C) 2015 Square, 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.
 */

// Kyler Conena
// Comp490

package retrofit2;

import com.google.common.reflect.TypeToken;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.List;
import java.util.concurrent.Executor;
import okhttp3.Request;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;

import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;

@SuppressWarnings("unchecked")
public final class EventCallAdapterFactoryTest {
  private static final Annotation[] NO_ANNOTATIONS = new Annotation[0];

  private final Retrofit retrofit = new Retrofit.Builder()
      .baseUrl("http://localhost:1")
      .build();
  private final Callback<String> callback = mock(Callback.class);
  private final Executor callbackExecutor = spy(new Executor() {
    @Override public void execute(Runnable runnable) {
      runnable.run();
    }
  });
  // Kyler Conena
  // Comp490
  private final CallAdapter.Factory factory = new EventCallAdapterFactory(callbackExecutor);

  @Test public void rawTypeThrows() {
    try {
      factory.get(Call.class, NO_ANNOTATIONS, retrofit);
      fail();
    } catch (IllegalArgumentException e) {
      assertThat(e).hasMessage("Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
    }
  }

  @Test public void responseType() {
    Type classType = new TypeToken<Call<String>>() {}.getType();
    assertThat(factory.get(classType, NO_ANNOTATIONS, retrofit).responseType())
        .isEqualTo(String.class);
    Type wilcardType = new TypeToken<Call<? extends String>>() {}.getType();
    assertThat(factory.get(wilcardType, NO_ANNOTATIONS, retrofit).responseType())
        .isEqualTo(String.class);
    Type genericType = new TypeToken<Call<List<String>>>() {}.getType();
    assertThat(factory.get(genericType, NO_ANNOTATIONS, retrofit).responseType())
        .isEqualTo(new TypeToken<List<String>>() {}.getType());
  }

  @Test public void adaptedCallExecute() throws IOException {
    Type returnType = new TypeToken<Call<String>>() {}.getType();
    CallAdapter<Call<?>> adapter =
        (CallAdapter<Call<?>>) factory.get(returnType, NO_ANNOTATIONS, retrofit);
    final Response<String> response = Response.success("Hi");
    Call<String> call = (Call<String>) adapter.adapt(new EmptyCall() {
      @Override public Response<String> execute() throws IOException {
        return response;
      }
    });
    assertThat(call.execute()).isSameAs(response);
  }
  
  

  @Test public void adaptedCallEnqueueUsesExecutorForSuccessCallback() {
    Type returnType = new TypeToken<Call<String>>() {}.getType();
    CallAdapter<Call<?>> adapter =
        (CallAdapter<Call<?>>) factory.get(returnType, NO_ANNOTATIONS, retrofit);
    final Response<String> response = Response.success("Hi");
    EmptyCall originalCall = new EmptyCall() {
      @Override public void enqueue(Callback<String> callback) {
        callback.onResponse(this, response);
      }
    };
    Call<String> call = (Call<String>) adapter.adapt(originalCall);
    call.enqueue(callback);
    verify(callbackExecutor).execute(any(Runnable.class));
    verify(callback).onResponse(call, response);
  }

  @Test public void adaptedCallEnqueueUsesExecutorForFailureCallback() {
    Type returnType = new TypeToken<Call<String>>() {}.getType();
    CallAdapter<Call<?>> adapter =
        (CallAdapter<Call<?>>) factory.get(returnType, NO_ANNOTATIONS, retrofit);
    final Throwable throwable = new IOException();
    EmptyCall originalCall = new EmptyCall() {
      @Override public void enqueue(Callback<String> callback) {
        callback.onFailure(this, throwable);
      }
    };
    Call<String> call = (Call<String>) adapter.adapt(originalCall);
    call.enqueue(callback);
    verify(callbackExecutor).execute(any(Runnable.class));
    verifyNoMoreInteractions(callbackExecutor);
    verify(callback).onFailure(call, throwable);
    verifyNoMoreInteractions(callback);
  }

  @Test public void adaptedCallCloneDeepCopy() {
    Type returnType = new TypeToken<Call<String>>() {}.getType();
    CallAdapter<Call<?>> adapter =
        (CallAdapter<Call<?>>) factory.get(returnType, NO_ANNOTATIONS, retrofit);
    Call<String> delegate = mock(Call.class);
    Call<String> call = (Call<String>) adapter.adapt(delegate);
    Call<String> cloned = call.clone();
    assertThat(cloned).isNotSameAs(call);
    verify(delegate).clone();
    verifyNoMoreInteractions(delegate);
  }

  @Test public void adaptedCallCancel() {
    Type returnType = new TypeToken<Call<String>>() {}.getType();
    CallAdapter<Call<?>> adapter =
        (CallAdapter<Call<?>>) factory.get(returnType, NO_ANNOTATIONS, retrofit);
    Call<String> delegate = mock(Call.class);
    Call<String> call = (Call<String>) adapter.adapt(delegate);
    call.cancel();
    verify(delegate).cancel();
    verifyNoMoreInteractions(delegate);
  }

  static class EmptyCall implements Call<String> {
    @Override public void enqueue(Callback<String> callback) {
      throw new UnsupportedOperationException();
    }

    @Override public boolean isExecuted() {
      return false;
    }

    @Override public Response<String> execute() throws IOException {
      throw new UnsupportedOperationException();
    }

    @Override public void cancel() {
      throw new UnsupportedOperationException();
    }

    @Override public boolean isCanceled() {
      return false;
    }

    @Override public Call<String> clone() {
      throw new UnsupportedOperationException();
    }

    @Override public Request request() {
      throw new UnsupportedOperationException();
    }
  }
}

@@ -3288,16 +3288,646 @@
  %7D%0A  %0A  
+/*@Test public void hasConverter() %7B%0A  EventCall%3CString%3E call = (EventCall%3CString%3E) adapter.adapt(new EmptyCall() %7B%0A      @Override public Response%3CString%3E execute() throws IOException %7B%0A        return response;%0A      %7D%0A    %7D);%0A    assertThat(call.getConverter()).isEqualTo(new TypeToken%3CConverter%3C?, ResponseBody%3E() %7B%7D.getType());%0A  %7D%0A  %0A  @Test public void isStri() %7B%0A   EventCall%3CString%3E call = (EventCall%3CString%3E) adapter.adapt(new EmptyCall() %7B%0A      @Override public Response%3CString%3E execute() throws IOException %7B%0A        return response;%0A      %7D%0A    %7D);%0A    assertThat(response.isEqualTo(new String %7B%7D.getType());%0A  %7D%0A  */
 %0A%0A  @Tes

Update EventCallAdapterFactoryTest.java