/*
 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#include "config.h"
#include "CSSVariablesDeclaration.h"

#include "CSSParser.h"
#include "CSSRule.h"
#include "CSSValueList.h"
#include "Document.h"
#include "ExceptionCode.h"

namespace WebCore {

CSSVariablesDeclaration::CSSVariablesDeclaration(StyleBase* parent, const Vector<String>& names, const Vector<RefPtr<CSSValue> >& values)
    : StyleBase(parent)
{
    m_variableNames = names;
    ASSERT(names.size() == values.size());
    unsigned s = names.size();
    for (unsigned i = 0; i < s; ++i)
        addParsedVariable(names[i], values[i], false);
}

CSSVariablesDeclaration::~CSSVariablesDeclaration()
{
}

String CSSVariablesDeclaration::getVariableValue(const String& variableName)
{
    CSSValue* val = m_variablesMap.get(variableName).get();
    if (val)
        return val->cssText();
    return "";
}

String CSSVariablesDeclaration::removeVariable(const String& variableName, ExceptionCode&)
{
    // FIXME: The spec has this method taking an exception code but no exceptions are
    // specified as being thrown.
    RefPtr<CSSValue> val = m_variablesMap.take(variableName);
    String result = val ? val->cssText() : "";
    if (val) {
        int s = m_variableNames.size();
        for (int i = 0; i < s; ++i) {
            if (m_variableNames[i] == variableName) {
                m_variableNames.remove(i);
                i--;
                s--;
            }
        }
        
        setNeedsStyleRecalc();
    }
    
    // FIXME: Communicate this change so that the document will update.
    return result;
}

void CSSVariablesDeclaration::setVariable(const String& variableName, const String& variableValue, ExceptionCode& excCode)
{
    // Try to parse the variable value into a Value*.  If it fails we throw an exception.
    CSSParser parser(useStrictParsing());
    if (!parser.parseVariable(this, variableName, variableValue)) // If the parse succeeds, it will call addParsedVariable (our internal method for doing the add) with the parsed Value*.
        excCode = SYNTAX_ERR;
    else
        setNeedsStyleRecalc();
}

void CSSVariablesDeclaration::addParsedVariable(const String& variableName, PassRefPtr<CSSValue> variableValue, bool updateNamesList)
{
// FIXME: Disabling declarations as variable values for now since they no longer have a common base class with CSSValues.
#if 0
    variableValue->setParent(this); // Needed to connect variables that are CSSMutableStyleDeclarations, since the parent couldn't be set until now.
#endif

    // Don't leak duplicates.  For multiple variables with the same name, the last one
    // declared will win.
    CSSValue* current = m_variablesMap.take(variableName).get();
    if (!current && updateNamesList)
        m_variableNames.append(variableName);
    m_variablesMap.set(variableName, variableValue);

    // FIXME: Communicate this change so the document will update.
}

CSSValueList* CSSVariablesDeclaration::getParsedVariable(const String& variableName)
{
    CSSValue* result = m_variablesMap.get(variableName).get();
    if (result->isValueList())
        return static_cast<CSSValueList*>(result);
    return 0;
}

CSSMutableStyleDeclaration* CSSVariablesDeclaration::getParsedVariableDeclarationBlock(const String&)
{
// FIXME: Disabling declarations as variable values for now since they no longer have a common base class with CSSValues.
#if 0
    StyleBase* result = m_variablesMap.get(variableName).get();

    if (result->isMutableStyleDeclaration())
        return static_cast<CSSMutableStyleDeclaration*>(result);
#endif
    return 0;
}

unsigned CSSVariablesDeclaration::length() const
{
    return m_variableNames.size();
}

String CSSVariablesDeclaration::item(unsigned index)
{
    if (index >= m_variableNames.size())
        return "";
    return m_variableNames[index];
}

CSSRule* CSSVariablesDeclaration::parentRule()
{
    return (parent() && parent()->isRule()) ? static_cast<CSSRule*>(parent()) : 0;
}

String CSSVariablesDeclaration::cssText() const
{
    String result = "{ ";
    unsigned s = m_variableNames.size();
    for (unsigned i = 0; i < s; ++i) {
        result += m_variableNames[i] + ": ";
        result += m_variablesMap.get(m_variableNames[i])->cssText();
        if (i < s - 1)
            result += "; ";
    }
    result += " }";
    return result;
}

void CSSVariablesDeclaration::setCssText(const String&)
{
    // FIXME: It's not clear if this is actually settable.
}

void CSSVariablesDeclaration::setNeedsStyleRecalc()
{
    // FIXME: Make this much better (it has the same problem CSSMutableStyleDeclaration does).
    StyleBase* root = this;
    while (StyleBase* parent = root->parent())
        root = parent;
    if (root->isCSSStyleSheet())
        static_cast<CSSStyleSheet*>(root)->doc()->updateStyleSelector();
}

}
