#include <WScom.h>

#include <WSCsheetListData.h>

WSCsheetListData::WSCsheetListData(){
  _seg_size = 16;
  _num = 0;
  _data = (void**)NULL;
}
WSCsheetListData::WSCsheetListData(long seg){
  _seg_size = seg;
  if (seg > 255){
    _seg_size = 0;
  } 
  _num = 0;
  _data = (void**)NULL;
}

WSCsheetListData::~WSCsheetListData(){
  if (_data != NULL){
    delete _data;
    _data = NULL;;
  }
  _num = 0;
}

long WSCsheetListData::getNum(){
  return _num;
}

long WSCsheetListData::setSize(long newSize)
{
  void**   newList = NULL;
  
  long addedNum = newSize - _num;
  if(addedNum == 0) {
    return WS_NO_ERR;
  }
  long pos;
  long num = _num;
  long segment_size = _seg_size;
  if (segment_size == 0){
    segment_size = 0x100;
  }

  newList = new void*[ (newSize / segment_size + 1) * segment_size ];
  if(addedNum < 0) {
     memcpy(newList, _data, sizeof(void*) * newSize);
     pos = num + addedNum;
     for(pos = num + addedNum; pos < num; pos++) {
       delete _data[pos];
     }
  } else {
     memcpy(newList, _data, sizeof(void*) * num);
     for(pos = num; pos < newSize; pos++) {
       newList[pos] = NULL;
     }
  }
  if(_data) {
    delete[] _data;
  }
  _data = newList;
  _num = newSize;
  
  return 0;
}

long WSCsheetListData::add(void* item,long pos){
  void**   newList = NULL;
  long num = _num;
  long segment_size = _seg_size;
  if (segment_size == 0){
    segment_size = 0x100;
  }
  if (pos == -1 || pos >= num){

    if (num % segment_size == 0){
      if (num != 0){
        newList = new void*[ (num /segment_size +1) * segment_size ];
        memcpy(newList,_data,sizeof(void*) * num);
        delete _data;
      }else{
        newList = new void*[ segment_size ];
      }
      _data = newList;
    }
    _data[num] = item;
    num++;
    _num = num;
    return 0;
  }

  if (pos < 0 ){
    pos = 0;
  }

  if (num != 0){
    if (num % segment_size == 0){
       long newlen = (num /segment_size +1) * segment_size;
       newList = new void*[newlen];
       memcpy(newList,_data,sizeof(void*) * pos);
       memcpy(&newList[pos+1],&_data[pos],sizeof(void*) * (num -pos));
       delete _data;
       _data = newList;
    }else{
       memmove(&_data[pos+1],&_data[pos],sizeof(void*) * (num - pos));
    }
  }else{
    newList = new void*[segment_size];
    _data = newList;
  }

  _data[pos] = item;
  num++;
  _num = num;
  return 0;
}

long WSCsheetListData::del(void* item){
  long i,fl;
  fl = -1;
  long num = _num;
  for(i =0; i < num; i++){
    if (_data[i] == item){
      if (num != 1){
        memcpy(&(_data[i]),&(_data[i+1]),sizeof(void*) * (num - i -1));
      }else{
        delete _data;
        _data = NULL;
      }
      num--;
      _num = num;
      return 0;
    }
  }
  return -1;
}

long WSCsheetListData::delPos(long fl){
  if (fl  < 0){
    return -1;
  }
  long num = _num;
  if (num == 0){
    return -1;
  }
  // over flow deleting pos  
  if (fl > num-1){
    return -1;
  }

  if (num != 1){
    memcpy(&(_data[fl]),&(_data[fl+1]),sizeof(void*) * (num - fl -1));
  }else{
    delete _data;
    _data = NULL;
  }
  num--;
  _num = num;
  return 0;
}

void WSCsheetListData::clear(){
  if (_data != NULL){
    delete _data;
    _data = NULL;;
  }
  _num = 0;
}

void WSCsheetListData::setData(long i,void* d){
  long num = _num;
  if (i < num && i > -1){
    _data[i] = d;
    return;
  }else{
    return ;
  }
}

void* WSCsheetListData::getData(long i){
  long num = _num;
  if (i < num && i > -1){
    return _data[i];
  }else if (i == -1 && num > 0){
    return _data[num-1];
  }else{
    return 0;
  }
}

void* WSCsheetListData::getBottomData(){
  long num = _num;
  if(num == 0){
    return 0;
  }
  return _data[num - 1];
}

void* WSCsheetListData::getTopData(){
  long num = _num;
  if(num == 0){
    return 0;
  }
  return _data[0];
}

void** WSCsheetListData::getBuf(){
  return _data;
}

WSCsheetListData::WSCsheetListData(WSCsheetListData& src){
  _data = NULL;
  _num = src._num;
  _seg_size = src._seg_size;
  long segment_size = _seg_size;
  if (segment_size == 0){
    segment_size = 0x100;
  }
  if (_num != 0){
    _data = new void*[ (_num /segment_size +1) * segment_size ];
    memcpy(_data,src._data,sizeof(void*)*_num);
  }
}

WSCsheetListData::WSCsheetListData(const WSCsheetListData& src){
  _data = NULL;
  _num = src._num;
  _seg_size = src._seg_size;
  long segment_size = _seg_size;
  if (segment_size == 0){
    segment_size = 0x100;
  }
  if (_num != 0){
    _data = new void*[ (_num /segment_size +1) * segment_size ];
    memcpy(_data,src._data,sizeof(void*)*_num);
  }
}


void*& WSCsheetListData::operator [] (long i){
  if (i < (long)_num && i > -1){
    return _data[i];
  }else if (i < 0 && _num > 0){
    return _data[_num-1];
  }
static void* dummy;
  dummy = 0;
  return dummy;
}
WSCsheetListData& WSCsheetListData::operator = (WSCsheetListData& src){
  if (&src != this){
    if (_data){
      delete _data;
      _data = NULL;
    }
    _num = src._num;
    _seg_size = src._seg_size;
    long segment_size = _seg_size;
    if (segment_size == 0){
      segment_size = 0x100;
    }
    if (_num != 0){
      _data = new void*[ (_num /segment_size +1) * segment_size ];
      memcpy(_data,src._data,sizeof(void*)*_num);
    }
  }
  return *this;
}
