package com.sap.dbtech.jdbc.packet;

import java.io.InputStream;
import java.io.Reader;
import java.sql.SQLException;

import com.sap.dbtech.jdbc.exceptions.NotImplemented;
import com.sap.dbtech.jdbc.exceptions.SQLExceptionSapDB;
import com.sap.dbtech.jdbc.translators.Putval;
import com.sap.dbtech.util.StructuredMem;
import com.sap.dbtech.vsp001.Packet;

/*

 created by D031096

 ========== licence begin GPL
    Copyright (C) 2002-2003 SAP AG

    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
    of the License, 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end


 */

public class DataPartVariable extends DataPart {
    private int fieldCount = 0;

    private int currentArgCount = 0;

    private int currentFieldCount = 0;

    private int currentFieldLen = 0;

    /**
     * @param rawMem
     * @param requestPacket
     */
    public DataPartVariable(StructuredMem rawMem, RequestPacket requestPacket) {
        super(rawMem, requestPacket);
    }

    public DataPartVariable(StructuredMem rawMem, int argCount) {
        super(rawMem, null);
        this.argCount = argCount;
    }

    public boolean nextRow() {
        if (this.currentArgCount >= this.argCount) {
            return false;
        } else {
            this.currentArgCount++;
            this.fieldCount = this.mem.getInt2(this.extent);
            this.extent += 2;
            this.currentFieldCount = 0;
            this.currentFieldLen = 0;
            return true;
        }
    }

    public boolean nextField() {
        if (this.currentFieldCount >= this.fieldCount) {
            return false;
        } else {
            this.currentFieldCount++;
            this.extent += this.currentFieldLen;
            this.currentFieldLen = this.getFieldLength(this.extent);
            this.extent += (this.currentFieldLen > 250) ? 3 : 1;
            return true;
        }
    }

    public int getCurrentFieldLen() {
        return this.currentFieldLen;
    }

    public int getCurrentOffset() {
        return this.extent;
    }

    public void addArg(int pos, int len) {
        ++this.argCount;
    }

    public void addRow(int fieldCount) {
        super.putInt2(fieldCount, this.extent);
        this.extent += 2;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.sap.dbtech.util.StructuredMem#getFieldLength(int)
     */
    public int getFieldLength(int offset) {
        int erg = this.getInt1(offset);
        if (erg <= 250) {
            return erg;
        } else {
            return this.getInt2(offset + 1);
        }
    }

    public int putFieldLength(int value, int offset) {
        if (value <= 250) {
            super.putInt1(value, offset);
            return 1;
        } else {
            super.putInt1(255, offset);
            super.putInt2(value, offset + 1);
            return 3;
        }
    }

    public void putDefineByte(int value, int offset) {
        //vardata part has no define byte
        return;
    }

    public void putBigUnicode(char[] value, int offsetInBytes, int lenInBytes) {
        int vallen = value.length;
        this.extent += this.putFieldLength(vallen, this.extent);
        super.putBigUnicode(value, this.extent, vallen);
        this.extent += vallen;
    }

    public void putBytes(byte[] value, int offset, int len) {
        int vallen = value.length;
        this.extent += this.putFieldLength(vallen, this.extent);
        super.putBytes(value, this.extent, vallen);
        this.extent += vallen;
    }

    public void putBytes(byte[] value, int offset) {
        int len = value.length;
        this.extent += this.putFieldLength(len, this.extent);
        super.putBytes(value, this.extent);
        this.extent += len;
    }

    public void putInt1(int value, int offset) {
        int len = 1;
        this.extent += this.putFieldLength(len, this.extent);
        super.putInt1(value, this.extent);
        this.extent += len;
    }

    public void putInt2(int value, int offset) {
        int len = 2;
        this.extent += this.putFieldLength(len, this.extent);
        super.putInt2(value, this.extent);
        this.extent += len;
    }

    public void putInt4(int value, int offset) {
        int len = 4;
        this.extent += this.putFieldLength(len, this.extent);
        super.putInt4(value, this.extent);
        this.extent += len;
    }

    public void putInt8(long value, int offset) {
        int len = 8;
        this.extent += this.putFieldLength(len, this.extent);
        super.putInt8(value, this.extent);
        this.extent += len;
    }

    public int putString(String value, int offset, int length) {
        int len = value.length();
        this.extent += this.putFieldLength(len, this.extent);
        int result = super.putString(value, this.extent, length);
        this.extent += len;
        return result;
    }

    public int putString(String value, int offset) {
        int len = value.length();
        this.extent += this.putFieldLength(len, this.extent);
        int result = super.putString(value, this.extent, len);
        this.extent += len;
        return result;
    }

    public void putStringBytes(byte[] value, int offset, int length) {
        int len = value.length;
        this.extent += this.putFieldLength(len, this.extent);
        super.putStringBytes(value, this.extent, len);
        this.extent += len;
    }

    public void putUnicodeBytes(byte[] value, int offset, int length) {
        int len = value.length;
        this.extent += this.putFieldLength(len, this.extent);
        super.putUnicodeBytes(value, this.extent, len);
        this.extent += len;
    }

    
    /**
     * @param pos  int
     * @param len  int
     */
    public void putNull(int pos, int len) {
        super.putInt1(Packet.csp1_fi_null_value_C, this.extent);
        this.extent += 1; 
        this.addArg (pos, len);
    }

    public void putDefault(int pos, int len) {
        super.putInt1(Packet.csp1_fi_default_value_C, this.extent);
        this.extent += 1; 
        this.addArg (pos, len);
    }

    public StructuredMem putDescriptor (
            int pos,
            byte [] descriptor)
        {
            int offset = this.extent+1;
            this.putBytes (descriptor, this.extent);
            return mem.getPointer (offset);
        }

    /* (non-Javadoc)
     * @see com.sap.dbtech.jdbc.packet.DataPart#fillWithOMSReader(java.io.Reader, int)
     */
    public boolean fillWithOMSReader(Reader stream, int rowSize) throws SQLException {
        throw new NotImplemented ();
    }

//    /* (non-Javadoc)
//     * @see com.sap.dbtech.jdbc.packet.DataPart#fillWithReader(java.io.Reader, com.sap.dbtech.util.StructuredMem, com.sap.dbtech.jdbc.translators.Putval)
//     */
//    public boolean fillWithReader(Reader reader, StructuredMem descriptorMark, Putval putval) throws SQLException {
//        throw new NotImplemented ();
//    }

    /* (non-Javadoc)
     * @see com.sap.dbtech.jdbc.packet.DataPart#fillWithProcedureReader(java.io.Reader, short)
     */
    public boolean fillWithProcedureReader(Reader reader, short rowCount) throws SQLException {
        throw new NotImplemented ();
    }

    /* (non-Javadoc)
     * @see com.sap.dbtech.jdbc.packet.DataPart#fillWithOMSReturnCode(int)
     */
    public void fillWithOMSReturnCode(int returncode) throws SQLExceptionSapDB {
        throw new NotImplemented ();
    }

    /* (non-Javadoc)
     * @see com.sap.dbtech.jdbc.packet.DataPart#fillWithOMSStream(java.io.InputStream, boolean)
     */
    public boolean fillWithOMSStream(InputStream stream, boolean asciiForUnicode) throws SQLException {
        throw new NotImplemented ();    }

    /* (non-Javadoc)
     * @see com.sap.dbtech.jdbc.packet.DataPart#fillWithProcedureStream(java.io.InputStream, short)
     */
    public boolean fillWithProcedureStream(InputStream stream, short rowCount) throws SQLException {
        throw new NotImplemented ();
    }

//    /* (non-Javadoc)
//     * @see com.sap.dbtech.jdbc.packet.DataPart#fillWithStream(java.io.InputStream, com.sap.dbtech.util.StructuredMem, com.sap.dbtech.jdbc.translators.Putval)
//     */
//    public boolean fillWithStream(InputStream stream, StructuredMem descriptorMark, Putval putval) throws SQLException {
//        throw new NotImplemented ();
//    }


}
