//
// Copyright (C) 1999-2004 Toshikaz Hirabayashi
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// TOSHIKAZ HIRABAYASHI BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// Except as contained in this notice, the name of Toshikaz Hirabayashi shall
// not be used in advertising or otherwise to promote the sale, use or other
// dealings in this Software without prior written authorization from
// Toshikaz Hirabayashi.

#include <WScom.h>
#include <WSDmwindowDev.h>
#include <WSCdevice.h>
#include <WSDdraw.h>
#include <WSCbase.h>
#include <WSCimageSet.h>
#include <WSCcolorSet.h>

WSMFclassInit(WSDmwindowDev,WSDdev);

WSDmwindowDev::WSDmwindowDev(){
  _w = 0;
  _h = 0;
}
void WSDmwindowDev::getGeometry(WSCushort* w,WSCushort* h){
  *w = _w;
  *h = _h;
}
WSCbool WSDmwindowDev::getReady(){
  long d1 = getDeviceResource();
  long d2 = getWindowResource();
  long d3 = getContextResource();
  if (d1 == -1 || d2 == -1 || d3 == -1){
     return False;
  }
  return True;
}

long WSDmwindowDev::beginDraw(short x,short y,WSCushort w,WSCushort h,WSCbool absolute,WSCbool scaling){

  if (scaling != False){
    double scale = getScale();
    if ( scale != 1){
      x = (short)((x + getXOffset()) * scale);
      y = (short)((y + getYOffset()) * scale);
      w = (WSCushort)(w * scale);
      h = (WSCushort)(h * scale);
    }else{
      x = x + getXOffset();
      y = y + getYOffset();
    }
  }

  WSDdraw* draw = getDraw();
  if (draw == NULL){
    return WS_ERR;
  }

  if (getReady() == False){
    return WS_ERR;
  }
  draw->beginDraw(this,getDeviceResource(),getWindowResource(),getContextResource());

  draw->setRegion(x,y,w,h);
  draw->setLineWidth(1);
  draw->setLineDashType(0);
  draw->setHatchPattern(0);
  return WS_NO_ERR;
}

long WSDmwindowDev::endDraw(){
  WSDdraw* draw = getDraw();
  if (draw == NULL){
    return WS_ERR;
  }
  draw->endDraw();

  return WS_NO_ERR;
}
WSDmwindowDev* WSDmwindowDev::getNewInstance(){
  WSDdev* dev = WSGIappDevice()->getDevObject("mwindowDev");
  if (dev != NULL){
    WSDmwindowDev* mdev = (WSDmwindowDev*)dev->cast("WSDmwindowDev");
    return mdev;
  }
  return NULL;
}
WSCuchar* WSDmwindowDev::getBuffer(){
  WSCuchar* buf = new WSCuchar[(_w * _h)*3];
  if (buf == NULL){
    return NULL;
  }
  long i;
  long j;
  for(i=0; i<_h; i++){
    for(j=0; j<_w; j++){
      WSCuchar r,g,b;
      getBufferRGB(j,i,&r,&g,&b);
      buf[_w*3*i + j*3] = r;
      buf[_w*3*i + j*3+1] = g;
      buf[_w*3*i + j*3+2] = b;
    }
  }
  return buf;
}
long WSDmwindowDev::setBuffer(WSCuchar* buf){
  if (buf == NULL){
    return WS_ERR;
  }
  long i;
  long j;
  for(i=0; i<_h; i++){
    for(j=0; j<_w; j++){
      WSCuchar r,g,b;
      r = buf[_w*3*i + j*3];
      g = buf[_w*3*i + j*3+1];
      b = buf[_w*3*i + j*3+2];
      setBufferRGB(j,i,r,g,b);
    }
  }
  return WS_NO_ERR;
}

long WSDmwindowDev::loadFile(char* fname){
  WSDimage* image = WSGIappImageSet()->getImage(fname);
  if (image == NULL){
    return WS_ERR;
  }
  WSCushort w = image->getImageWidth();
  WSCushort h = image->getImageHeight();
  if (w == 0 || h == 0){
    image->destroyImage();
    return WS_ERR;
  }
  long ret = createPixmap(w,h);
  if (ret == WS_ERR){
    return WS_ERR;
  }
  beginDraw(0,0,w,h);
  WSDcolor* col= WSGIappColorSet()->getColor("#000000");
  setForeColor(col);
  setBackColor(col);
  drawFillRect(0,0,w,h);
  drawImage(0,0,w,h,image,WS_LEFT_TOP);
  endDraw();
  return WS_NO_ERR;
}
long WSDmwindowDev::saveFile(char* fname,long type){
  if (_w == 0 || _h == 0){
    return WS_ERR;
  }
  if (type == WS_IMAGE_BMP){
    long size_of_header = 0x36;
    long depth = 4;
    long filesize = _w * _h * depth + size_of_header;

    char* bmpFile = new char[filesize];
    if (bmpFile == NULL){
      return WS_ERR;
    }

    memset(bmpFile, 0, size_of_header);
    bmpFile[0] = (char)0x42;
    bmpFile[1] = (char)0x4d;
    bmpFile[2] = (char)((filesize)       & 0x000000ff);
    bmpFile[3] = (char)((filesize >> 8)  & 0x000000ff);
    bmpFile[4] = (char)((filesize >> 16) & 0x000000ff);
    bmpFile[5] = (char)((filesize >> 24) & 0x000000ff);
    bmpFile[0x0a] = (char)0x36; //32bit color
    bmpFile[0x0e] = (char)0x28;
    bmpFile[0x12] = (char)(_w & 0x00ff); 
    bmpFile[0x13] = (char)((_w & 0xff00) >> 8); 
    bmpFile[0x16] = (char)(_h & 0x00ff); 
    bmpFile[0x17] = (char)((_h & 0xff00) >> 8); 
    bmpFile[0x1a] = (char)1;
    bmpFile[0x1c] = (char)depth*8;
    bmpFile[0x22] = (char)((filesize -0x36)      & 0x000000ff);
    bmpFile[0x23] = (char)(((filesize -0x36)>> 8)  & 0x000000ff);
    bmpFile[0x24] = (char)(((filesize -0x36)>> 16) & 0x000000ff);
    bmpFile[0x25] = (char)(((filesize -0x36)>> 24) & 0x000000ff);

    long ret = initBuffer();
    if (ret != WS_NO_ERR){
      delete bmpFile;
      return WS_ERR;
    } 

    int i=0x36;
    long x,y;
    for(y=_h-1; 0 <= y; y--){
      for(x=0; x<_w; x++){
        WSCuchar r,g,b;
        getBufferRGB(x,y,&r,&g,&b);
        bmpFile[i] = b;
        bmpFile[i+1] = g;
        bmpFile[i+2] = r;
        bmpFile[i+3] = 0;
        i+=depth;
      }
    }
    FILE* fp = fopen(fname,"wb");
    if (fp != NULL){
      int ret = fwrite(bmpFile,1,filesize,fp);
      if (ret < filesize){
        fclose(fp);
        delete bmpFile;
        return WS_ERR;
      }
      fclose(fp);
      delete bmpFile;
      return WS_NO_ERR;
    }else{
      delete bmpFile;
      return WS_ERR;
    }
  }
  return WS_ERR;
}

