/***************************************************************************
                          SIMPLY POWERFUL TOOLKIT (SPTK)
                          CExcelPalette.cpp  -  description
                             -------------------
    begin                : Wed May 12 2004
    copyright            : (C) 2000-2006 by Alexey S.Parshin
    email                : alexeyp@gmail.com
 ***************************************************************************/

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

   This library 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 Library
   General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; if not, write to the Free Software Foundation, 
   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.

   Please report all bugs and problems to "alexeyp@gmail.com"
 ***************************************************************************/

#include <string.h>
#include <sptk3/CException.h>
#include <sptk3/excel/CExcelPalette.h>

using namespace sptk;

const unsigned CExcelPalette::standardPalette[8] = {
   0x000000,
   0xffffff,
   0x0000ff,
   0x00ff00,
   0xff0000,
   0x00ffff,
   0xff00ff,
   0xffff00
};

void CExcelPalette::clear() {
   memset(m_data,0,258);
   m_data[0] = char(0x40);
   memcpy(m_data + 2,standardPalette,sizeof(CExcelPalette::standardPalette));
   m_colorMap.clear();
   memset(m_colors,0,sizeof(m_colors));
}

unsigned CExcelPalette::colorIndex(unsigned rgbColor) {
   rgbColor = rgbColor & 0xF8F8F8;
   std::map<unsigned,unsigned>::iterator itor = m_colorMap.find(rgbColor);
   if (itor != m_colorMap.end())
      return itor->second + 8;
   unsigned colorIndex = m_colorMap.size();
   if (colorIndex >= 56)
      throw CException("The palette is full - can't add any new colors");
   m_colorMap[rgbColor] = colorIndex;
   m_colors[colorIndex] = rgbColor;
   return colorIndex + 8;
}

unsigned CExcelPalette::colorForIndex(unsigned colorIndex) const {
   if (colorIndex < 8)
      return standardPalette[colorIndex];
   colorIndex -= 8;
   if (colorIndex >= 56)
      throw CException("Invalid palette color index - should be 0 to 63");
   return m_colors[colorIndex];
}

void CExcelPalette::saveRecords(CExcelRecordsBuffer& records) {
   unsigned colorCount = m_colorMap.size();
   if (colorCount == 0) colorCount = 56; // Generate default palette
   m_bytes = colorCount * 4 + 2;
   m_data = (char *)realloc(m_data,m_bytes+1);
   CExcelRecord::setshort(m_data,0,colorCount);

   if (m_colorMap.size()) {
      std::map<unsigned,unsigned>::iterator itor = m_colorMap.begin();
      for (; itor != m_colorMap.end(); itor++) {
         unsigned rgbColor = itor->first;
         unsigned colorIndex = itor->second;
         unsigned offset = 2 + colorIndex * 4;
         CExcelRecord::setint(m_data,offset,rgbColor);
      }
      records.append(this);
   }
}
