/*
 * Copyright Terracotta, 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 org.terracotta.healthchecker;

import java.util.Timer;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.terracotta.entity.EndpointDelegate;
import org.terracotta.entity.EntityClientEndpoint;
import org.terracotta.entity.EntityResponse;
import org.terracotta.entity.InvokeFuture;
import org.terracotta.entity.MessageCodecException;
import org.terracotta.exception.EntityException;

/**
 *
 */
public class HealthCheckerClient implements HealthCheck {
  
  private final EntityClientEndpoint<HealthCheckReq, HealthCheckRsp> endpoint;
  private final Timer driver;

  public HealthCheckerClient(EntityClientEndpoint<HealthCheckReq, HealthCheckRsp> endpoint) {
    this.endpoint = endpoint;
    this.driver = new Timer("healthcheck timer - " + endpoint.hashCode(), true);
    this.endpoint.setDelegate(new HealthCheckerDelegate());
  }

  @Override
  public Future<String> ping(String message) {
    try {
//  don't add any extra acks here.  This is pure ping-pong
      return wrapFuture(endpoint.beginInvoke().message(new HealthCheckReq(message)).replicate(false).invoke());
    } catch (MessageCodecException codec) {
      throw new RuntimeException(codec);
    }
  }
  
  private Future<String> wrapFuture(final InvokeFuture<HealthCheckRsp> invoke) {
    return new Future<String>() {
      @Override
      public boolean cancel(boolean mayInterruptIfRunning) {
        return  false;
      }

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

      @Override
      public boolean isDone() {
        return invoke.isDone();
      }

      @Override
      public String get() throws InterruptedException, ExecutionException {
        try {
//  not intended for use but implemented in case a future use arises
          return invoke.get().toString();
        } catch (EntityException ee) {
          throw new ExecutionException(ee);
        }
      }

      @Override
      public String get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
        try {
          return invoke.getWithTimeout(timeout, unit).toString();
        } catch (EntityException ee) {
          throw new ExecutionException(ee);
        }
      } 
    };
  }

  @Override
  public void close() {
    endpoint.close();
    driver.cancel();
  }

  @Override
  public Timer getTimer() {
    return driver;
  }

  class HealthCheckerDelegate implements EndpointDelegate {
    @Override
    public void handleMessage(EntityResponse messageFromServer) {
  // do nothing
    }

    @Override
    public byte[] createExtendedReconnectData() {
  // do nothing
      return new byte[0];
    }

    @Override
    public void didDisconnectUnexpectedly() {
      driver.cancel();
    }
  }
}

@@ -1060,57 +1060,8 @@
 ion;
-%0Aimport org.terracotta.exception.EntityException;
 %0A%0A/*
@@ -2471,38 +2471,43 @@
        %7D catch (
-Entity
+Interrupted
 Exception ee) %7B%0A
@@ -2492,34 +2492,100 @@
 ruptedException 
-ee
+interrupt) %7B%0A          throw interrupt;%0A        %7D catch (Throwable t
 ) %7B%0A          th
@@ -2603,34 +2603,33 @@
 cutionException(
-ee
+t
 );%0A        %7D%0A   
@@ -2868,22 +2868,27 @@
  catch (
-Entity
+Interrupted
 Exceptio
@@ -2889,18 +2889,84 @@
 ception 
-ee
+interrupt) %7B%0A          throw interrupt;%0A        %7D catch (Throwable t
 ) %7B%0A    
@@ -3000,18 +3000,17 @@
 ception(
-ee
+t
 );%0A     

Fix #292: Catch all throwables in get