package org.chenyang.http.impl.execchain;

import org.chenyang.http.HttpEntity;
import org.chenyang.http.HttpResponse;
import org.chenyang.http.conn.EofSensorInputStream;
import org.chenyang.http.conn.EofSensorWatcher;
import org.chenyang.http.entity.HttpEntityWrapper;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketException;

class ResponseEntityProxy extends HttpEntityWrapper implements EofSensorWatcher {
   private final ConnectionHolder connHolder;

   public static void enchance(HttpResponse response, ConnectionHolder connHolder) {
      HttpEntity entity = response.getEntity();
      if (entity != null && entity.isStreaming() && connHolder != null) {
         response.setEntity(new ResponseEntityProxy(entity, connHolder));
      }

   }

   ResponseEntityProxy(HttpEntity entity, ConnectionHolder connHolder) {
      super(entity);
      this.connHolder = connHolder;
   }

   private void cleanup() throws IOException {
      if (this.connHolder != null) {
         this.connHolder.close();
      }

   }

   private void abortConnection() {
      if (this.connHolder != null) {
         this.connHolder.abortConnection();
      }

   }

   public void releaseConnection() {
      if (this.connHolder != null) {
         this.connHolder.releaseConnection();
      }

   }

   public boolean isRepeatable() {
      return false;
   }

   public InputStream getContent() throws IOException {
      return new EofSensorInputStream(this.wrappedEntity.getContent(), this);
   }

   public void consumeContent() throws IOException {
      this.releaseConnection();
   }

   public void writeTo(OutputStream outStream) throws IOException {
      try {
         if (outStream != null) {
            this.wrappedEntity.writeTo(outStream);
         }

         this.releaseConnection();
      } catch (IOException ex) {
         this.abortConnection();
         throw ex;
      } catch (RuntimeException ex) {
         this.abortConnection();
         throw ex;
      } finally {
         this.cleanup();
      }

   }

   public boolean eofDetected(InputStream wrapped) throws IOException {
      try {
         if (wrapped != null) {
            wrapped.close();
         }

         this.releaseConnection();
      } catch (IOException ex) {
         this.abortConnection();
         throw ex;
      } catch (RuntimeException ex) {
         this.abortConnection();
         throw ex;
      } finally {
         this.cleanup();
      }

      return false;
   }

   public boolean streamClosed(InputStream wrapped) throws IOException {
      try {
         boolean open = this.connHolder != null && !this.connHolder.isReleased();

         try {
            if (wrapped != null) {
               wrapped.close();
            }

            this.releaseConnection();
         } catch (SocketException ex) {
            if (open) {
               throw ex;
            }
         }
      } catch (IOException ex) {
         this.abortConnection();
         throw ex;
      } catch (RuntimeException ex) {
         this.abortConnection();
         throw ex;
      } finally {
         this.cleanup();
      }

      return false;
   }

   public boolean streamAbort(InputStream wrapped) throws IOException {
      this.cleanup();
      return false;
   }

   public String toString() {
      StringBuilder sb = new StringBuilder("ResponseEntityProxy{");
      sb.append(this.wrappedEntity);
      sb.append('}');
      return sb.toString();
   }
}
