/*
_____       _    _    Corso   Italia,  178
(_|__   .  (_   |_|_  56125           Pisa
(_|_) |)|(()_)()| |   tel.  +39  050 46380
  |   |               picosoft@picosoft.it

 Copyright (C) Picosoft s.r.l. 1995-2002

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2, or (at your option)
 any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/
package IT.picosoft.jdbc;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;

public class PicoInputStream extends InputStream
{
   protected PicoDbApi odbcApi;
   protected OdbcStatement hStmt;
   protected int column;
   protected short type;
   public static final short ASCII = 1;
   public static final short UNICODE = 2;
   public static final short BINARY = 3;
   public static final short LOCAL = 4;
   protected byte localByteArray[];
   protected int localOffset;
   protected boolean invalid;
   protected boolean highRead;
   protected int sqlType;
   protected byte buf[];
   public static final int MAX_BUF_LEN = 5120;
   protected int convertType;
   public static final int CONVERT_NONE = 0;
   public static final int CONVERT_UNICODE = 1;
   public static final int CONVERT_ASCII = 2;
   public static final int CONVERT_BOTH = 3;
   protected int convertMultiplier;
   protected int bytesInBuf;
   protected int bufOffset;
   protected Statement ownerStatement;

   public PicoInputStream(PicoDbApi api, OdbcStatement stmt, int col, short ty,
                     int k, Statement statement)
   {
      odbcApi = api;
      hStmt = stmt;
      column = col;
      type = ty;
      invalid = false;
      ownerStatement = statement;
      sqlType = -2;
      switch(k) {
      case -1: 
      case 1: // '\001'
      case 12: // '\f'
         sqlType = 1;
         break;

      }
      convertMultiplier = 1;
      convertType = 0;
      switch(type) {
      default:
         break;
      case 1: // '\001'
         if(sqlType == -2) {
            convertMultiplier = 2;
            convertType = 2;
         }
         break;
      case 2: // '\002'
         if(sqlType == -2) {
            convertType = 3;
            convertMultiplier = 4;
         } else {
            convertType = 1;
            convertMultiplier = 2;
         }
         break;

      }
      buf = new byte[5120 * convertMultiplier];
      bytesInBuf = 0;
      bufOffset = 0;
   }

   public PicoInputStream(PicoDbApi api, OdbcStatement stmt, int col, byte abyte0[]) {
      odbcApi = api;
      hStmt = stmt;
      column = col;
      type = 4;
      localByteArray = abyte0;
      localOffset = 0;
      invalid = false;
   }

   public int available() throws IOException {
      throw new IOException();
   }

   protected int convertData(byte abyte0[], int i) {
      if(convertType == 0)
         return i;
      String s = "0123456789ABCDEF";
      if(i <= 0)
         return i;
      for(int j = i - 1; j >= 0; j--)
         if(convertType == 3) {
            abyte0[j * 4 + 3] = (byte)s.charAt(abyte0[j] & 0xf);
            abyte0[j * 4 + 2] = 0;
            abyte0[j * 4 + 1] = (byte)s.charAt(abyte0[j] >> 4 & 0xf);
            abyte0[j * 4] = 0;
         } else if(convertType == 2) {
            abyte0[j * 2 + 1] = (byte)s.charAt(abyte0[j] & 0xf);
            abyte0[j * 2] = (byte)s.charAt(abyte0[j] >> 4 & 0xf);
         } else {
            abyte0[j * 2 + 1] = abyte0[j];
            abyte0[j * 2] = 0;
         }

      return i * convertMultiplier;
   }

   public void invalidate() {
      invalid = true;
   }

   public int read() throws IOException {
      byte abyte0[] = new byte[1];
      int i = read(abyte0);
      if(i != -1)
         i = abyte0[0] & 0xff;
      return i;
   }

   public int read(byte abyte0[]) throws IOException {
      if(abyte0.length == 0)
         return -1;
      int i = 0;
      if(invalid)
         throw new IOException("InputStream is no longer valid - the Statement has been closed, or the cursor has been moved");
      switch(type) {
      case 4: // '\004'
         i = abyte0.length;
         if(localOffset + i > localByteArray.length)
            i = localByteArray.length - localOffset;
         if(i == 0) {
            i = -1;
         } else {
            for(int j = 0; j < i; j++)
               abyte0[j] = localByteArray[localOffset + j];

            localOffset += i;
         }
         break;

      default:
         i = readData(abyte0);
         break;

      }
      return i;
   }

   public int read(byte abyte0[], int i, int j) throws IOException {
      throw new IOException("Method not implemented");
   }

   protected int readBinaryData(byte abyte0[], int i) throws IOException {
      throw new IOException("Method not implemented");
/*TODO 
      int j = 0;
      try {
         j = odbcApi.SQLGetDataBinary(hStmt, column, -2, abyte0, i);
      } catch(PicoSQLWarning jdbcodbcsqlwarning) {
         Integer integer = (Integer)jdbcodbcsqlwarning.value;
         j = integer.intValue();
      } catch(SQLException sqlexception) {
         throw new IOException(sqlexception.getMessage());
      }
      return j;
*/

   }

   protected int readData(byte abyte0[]) throws IOException {
      int i = -1;
      int j;
      for(j = 0; bytesInBuf != -1 && j < abyte0.length;)
         if(bufOffset >= bytesInBuf) {
            bytesInBuf = readBinaryData(buf, 5120);
            bytesInBuf = convertData(buf, bytesInBuf);
            bufOffset = 0;
         } else {
            abyte0[j] = buf[bufOffset];
            j++;
            bufOffset++;
         }

      if(j > 0)
         i = j;
      return i;
   }
}
