
/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */


#include "SkAnimateBase.h"
#include "SkAnimateMaker.h"
#include "SkAnimateProperties.h"
#include "SkAnimatorScript.h"
#include "SkDisplayApply.h"
#include "SkDrawable.h"

#if SK_USE_CONDENSED_INFO == 0

const SkMemberInfo SkAnimateBase::fInfo[] = {
    SK_MEMBER(begin, MSec),
    SK_MEMBER_ARRAY(blend, Float),
    SK_MEMBER(dur, MSec),
    SK_MEMBER_PROPERTY(dynamic, Boolean),
    SK_MEMBER(field, String),   // name of member info in target
    SK_MEMBER(formula, DynamicString),
    SK_MEMBER(from, DynamicString),
    SK_MEMBER(lval, DynamicString),
    SK_MEMBER_PROPERTY(mirror, Boolean),
    SK_MEMBER(repeat, Float),
    SK_MEMBER_PROPERTY(reset, Boolean),
    SK_MEMBER_PROPERTY(step, Int),
    SK_MEMBER(target, DynamicString),
    SK_MEMBER(to, DynamicString),
    SK_MEMBER_PROPERTY(values, DynamicString)
};

#endif

DEFINE_GET_MEMBER(SkAnimateBase);

SkAnimateBase::SkAnimateBase() : begin(0), dur(1), repeat(SK_Scalar1),
        fApply(NULL), fFieldInfo(NULL), fFieldOffset(0), fStart((SkMSec) -1), fTarget(NULL),
        fChanged(0), fDelayed(0), fDynamic(0), fHasEndEvent(0), fHasValues(0),
        fMirror(0), fReset(0), fResetPending(0), fTargetIsScope(0) {
    blend.setCount(1);
    blend[0] = SK_Scalar1;
}

SkAnimateBase::~SkAnimateBase() {
    SkDisplayTypes type = fValues.getType();
    if (type == SkType_String || type == SkType_DynamicString) {
        SkASSERT(fValues.count() == 1);
        delete fValues[0].fString;
    }
}

int SkAnimateBase::components() {
    return 1;
}

SkDisplayable* SkAnimateBase::deepCopy(SkAnimateMaker* maker) {
    SkAnimateBase* result = (SkAnimateBase*) INHERITED::deepCopy(maker);
    result->fApply = fApply;
    result->fFieldInfo =fFieldInfo;
    result->fHasValues = false;
    return result;
}

void SkAnimateBase::dirty() {
    fChanged = true;
}

#ifdef SK_DUMP_ENABLED
void SkAnimateBase::dump(SkAnimateMaker* maker) {
    dumpBase(maker);
    if (target.size() > 0)
        SkDebugf("target=\"%s\" ", target.c_str());
    else if (fTarget && strcmp(fTarget->id, ""))
        SkDebugf("target=\"%s\" ", fTarget->id);
    if (lval.size() > 0)
        SkDebugf("lval=\"%s\" ", lval.c_str());
    if (field.size() > 0)
        SkDebugf("field=\"%s\" ", field.c_str());
    else if (fFieldInfo)
        SkDebugf("field=\"%s\" ", fFieldInfo->fName);
    if (formula.size() > 0)
        SkDebugf("formula=\"%s\" ", formula.c_str());
    else {
        if (from.size() > 0)
            SkDebugf("from=\"%s\" ", from.c_str());
        SkDebugf("to=\"%s\" ", to.c_str());
    }
    if (begin != 0) {
        SkDebugf("begin=\"%g\" ", SkScalarToFloat(SkScalarDiv(begin,1000)));
    }
}
#endif

SkDisplayable* SkAnimateBase::getParent() const {
    return (SkDisplayable*) fApply;
}

bool SkAnimateBase::getProperty(int index, SkScriptValue* value) const {
    int boolResult;
    switch (index) {
        case SK_PROPERTY(dynamic):
            boolResult = fDynamic;
            goto returnBool;
        case SK_PROPERTY(mirror):
            boolResult = fMirror;
            goto returnBool;
        case SK_PROPERTY(reset):
            boolResult = fReset;
returnBool:
            value->fOperand.fS32 = SkToBool(boolResult);
            value->fType = SkType_Boolean;
            break;
        case SK_PROPERTY(step):
            if (fApply == NULL)
                return false;    // !!! notify there's an error?
            fApply->getStep(value);
            break;
        case SK_PROPERTY(values):
            value->fOperand.fString = (SkString*) &to;
            value->fType = SkType_String;
            break;
        default:
            SkASSERT(0);
            return false;
    }
    return true;
}

bool SkAnimateBase::hasExecute() const
{
    return false;
}

void SkAnimateBase::onEndElement(SkAnimateMaker& maker) {
    fChanged = false;
    setTarget(maker);
    if (field.size()) {
        SkASSERT(fTarget);
        fFieldInfo = fTarget->getMember(field.c_str());
        field.reset();
    }
    if (lval.size()) {
        // lval must be of the form x[y]
        const char* lvalStr = lval.c_str();
        const char* arrayEnd = strchr(lvalStr, '[');
        if (arrayEnd == NULL)
            return; //should this return an error?
        size_t arrayNameLen = arrayEnd - lvalStr;
        SkString arrayStr(lvalStr, arrayNameLen);
        SkASSERT(fTarget);  //this return an error?
        fFieldInfo = fTarget->getMember(arrayStr.c_str());
        SkString scriptStr(arrayEnd + 1, lval.size() - arrayNameLen - 2);
        SkAnimatorScript::EvaluateInt(maker, this, scriptStr.c_str(), &fFieldOffset);
    }
}

void SkAnimateBase::packARGB(SkScalar array[], int count, SkTDOperandArray* converted)
{
    SkASSERT(count == 4);
    converted->setCount(1);
    SkColor color = SkColorSetARGB(SkScalarRoundToInt(array[0]),
                                   SkScalarRoundToInt(array[1]),
                                   SkScalarRoundToInt(array[2]),
                                   SkScalarRoundToInt(array[3]));
    (*converted)[0].fS32 = color;
}



void SkAnimateBase::refresh(SkAnimateMaker& ) {
}

bool SkAnimateBase::setParent(SkDisplayable* apply) {
    SkASSERT(apply->isApply());
    fApply = (SkApply*) apply;
    return false;
}

bool SkAnimateBase::setProperty(int index, SkScriptValue& value) {
    bool boolValue = SkToBool(value.fOperand.fS32);
    switch (index) {
        case SK_PROPERTY(dynamic):
            fDynamic = boolValue;
            goto checkForBool;
        case SK_PROPERTY(values):
            fHasValues = true;
            SkASSERT(value.fType == SkType_String);
            to = *value.fOperand.fString;
            break;
        case SK_PROPERTY(mirror):
            fMirror = boolValue;
            goto checkForBool;
        case SK_PROPERTY(reset):
            fReset = boolValue;
checkForBool:
            SkASSERT(value.fType == SkType_Boolean);
            break;
        default:
            return false;
    }
    return true;
}

void SkAnimateBase::setTarget(SkAnimateMaker& maker) {
    if (target.size()) {
        SkAnimatorScript engine(maker, this, SkType_Displayable);
        const char* script = target.c_str();
        SkScriptValue scriptValue;
        bool success = engine.evaluateScript(&script, &scriptValue);
        if (success && scriptValue.fType == SkType_Displayable)
            fTarget = scriptValue.fOperand.fDrawable;
        else if (maker.find(target.c_str(), (SkDisplayable**) &fTarget) == false) {
            if (fApply->getMode() == SkApply::kMode_create)
                return; // may not be an error
            if (engine.getError() != SkScriptEngine::kNoError)
                maker.setScriptError(engine);
            else {
                maker.setErrorNoun(target);
                maker.setErrorCode(SkDisplayXMLParserError::kTargetIDNotFound);
            }
            return;
        }
        if (fApply && fApply->getMode() != SkApply::kMode_create)
            target.reset();
    }
}

bool SkAnimateBase::targetNeedsInitialization() const {
    return false;
}
