/*
 * This file is part of libtqtvd_astronav
 *
 * Copyright (C) 2008-2017 TQTVD Software
 * Copyright (C) 2017 Mirakulo Software (mirakulo@mirakulo.com)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

#include "kjs/wk_config.h"
#include "BALConfiguration.h"
#include "BCFontPlatformDataPrivateGraphicManager.h"
#include <font/BTFontPlatformData.h>
#include "BTLogHelper.h"
#include <graphics/BIGraphicsDevice.h>
#include "CString.h"

#include <sys/stat.h>
#include <string>

#include "IGraphicManagerAdapter.h"

IMPLEMENT_CREATE_DELETE(BIFontPlatformDataPrivate, BCFontPlatformDataPrivateGraphicManager);

using WebCore::CString;
using WebCore::StringImpl;

extern IGraphicManagerAdapter * g_graphicManager;

namespace BAL {

int BCFontPlatformDataPrivateGraphicManager::m_isInitialized = 0;

BCFontPlatformDataPrivateGraphicManager::BCFontPlatformDataPrivateGraphicManager()
{
    m_font = NULL;
	if (g_graphicManager)
	    m_fontMapping = g_graphicManager->CreateFontMapping();
    DBGML(MODULE_FONTS, LEVEL_INFO, "\nconstrutor(): m_isInitialized=%d\n", m_isInitialized);
}

BCFontPlatformDataPrivateGraphicManager::~BCFontPlatformDataPrivateGraphicManager()
{
    if (m_font && g_graphicManager) {
		if (g_graphicManager && m_font)
		{
    	    g_graphicManager->DestroyFont(m_font);
    	    m_font = NULL;
		}
    }

	if (m_font)
	{
		delete m_font;
        m_font = NULL;
	}

    if (m_fontMapping && g_graphicManager) {
		if (g_graphicManager && m_fontMapping)
    	    g_graphicManager->DestroyFontMapping(m_fontMapping);
        m_fontMapping = NULL;
    }
    m_isInitialized--;
    DBGML(MODULE_FONTS, LEVEL_INFO, "\ndestrutor(): m_isInitialized=%d\n", m_isInitialized);
}

int BCFontPlatformDataPrivateGraphicManager::init()
{
    m_isInitialized++;
    DBGML(MODULE_FONTS, LEVEL_INFO, "\ninit(): m_isInitialized=%d\n", m_isInitialized);
    return m_isInitialized;
}

void BCFontPlatformDataPrivateGraphicManager::configureFontMapping(const FontDescription& fontDescription, const AtomicString& familyName)
{
    std::string _family;
    std::string _face;
    std::string _style;

    //FIXME: Se pediu { 'serif', 'sans-serif', 'monospace', 'cursive', 'fantasy' }
    // (que sao as palavras reservadas para uso em <gerenric-family>)
    // entao '_family' fica vazio!!! Porque???
    _family = fontDescription.family().family().domString().latin1().data();

    switch (fontDescription.genericFamily ())
    {
        case FontDescription::SerifFamily:
            _face = "serif";
            break;
        case FontDescription::SansSerifFamily:
            _face = "sans-serif";
            break;
        case FontDescription::MonospaceFamily:
            _face = "monospace";
            break;
        case FontDescription::NoFamily:
            // FIXME: esta sempre retornando 'NoFamily' ???
            _face = "no-family";
            break;
        case FontDescription::StandardFamily:
        default:
            _face = "sans-serif";
            break;
    }

    if (fontDescription.bold () && fontDescription.italic ())
        _style = "bold-italic";
    else if (fontDescription.bold ())
        _style = "bold";
    else if (fontDescription.italic ())
        _style = "italic"; //== oblique
    else
        _style = "regular";

    DBGML(MODULE_FONTS, LEVEL_INFO, "\n_family='%s' _face='%s' _style='%s'\n", _family.c_str(), _face.c_str(), _style.c_str());

    /* Se nao foi encontrada uma familia entao define '_family' como 'Default'. */
    if (_family.empty())
        _family = "default";
    //assert(m_font != NULL);
    m_font = m_fontMapping->getFont ((char *)_family.c_str(), (char *)_style.c_str(), static_cast<uint> (fontDescription.specifiedSize ()));

    if (m_font == NULL) {
        _family = "default";
        m_font = m_fontMapping->getFont ((char *)_family.c_str(), (char *)_style.c_str(), static_cast<uint> (fontDescription.specifiedSize ()));
    }

    if (m_font == NULL) {
        printf("\n\n\n ERROR: no way, m_font is NULL !!! \n\n\n");
    }
}

bool BCFontPlatformDataPrivateGraphicManager::isFixedPitch()
{
    DBGML(MODULE_FONTS, LEVEL_INFO, "\nNOT IMPLEMENTED: BCFontPlatformDataPrivateGraphicManager::isFixedPitch() = false\n");
    // TODO: a implementacao nao eh mandatoria, mas pode ser uma otimizacao a ser feita.
    return false;
}

unsigned BCFontPlatformDataPrivateGraphicManager::hash() const
{
	unsigned hash = m_font->GetSize();
	if (m_font->GetFamily())
		hash ^= StringImpl::computeHash(m_font->GetFamily());
	if (m_font->GetStyle())
		hash ^= StringImpl::computeHash(m_font->GetStyle());

	return  hash;
}

static inline bool areEquals(const char* a, const char* b){
	if (!a && !b)
		return true;
	if (a && b)
		return strcmp(a,b) == 0; /* strcmp returns -1,0,1 on whether a is <,==,> b */
	return false;
}

bool BCFontPlatformDataPrivateGraphicManager::isEqual(const BIFontPlatformDataPrivate* other) const
{

	if (!other)
		return false;
    const BCFontPlatformDataPrivateGraphicManager* compare = static_cast<const BCFontPlatformDataPrivateGraphicManager*> (other);

    IGraphicManagerAdapterFont* other_font = compare->getFont();

    if (!other_font)
    		return false;


    bool ret = 	   areEquals(m_font->GetFamily(),other_font->GetFamily())
			&& areEquals(m_font->GetStyle() ,other_font->GetStyle())
			&& m_font->GetSize() == other_font->GetSize();

    return ret;
}

} //namespace BAL
