
/*
 * 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 "SkDisplayAdd.h"
#include "SkAnimateMaker.h"
#include "SkDisplayApply.h"
#include "SkDisplayList.h"
#include "SkDrawable.h"
#include "SkDrawGroup.h"

#if SK_USE_CONDENSED_INFO == 0

const SkMemberInfo SkAdd::fInfo[] = {
    SK_MEMBER(mode, AddMode),
    SK_MEMBER(offset, Int),
    SK_MEMBER(use, Drawable),
    SK_MEMBER(where, Drawable)
};

#endif

// start here;
// add onEndElement to turn where string into f_Where
// probably need new SkAnimateMaker::resolve flavor that takes
// where="id", where="event-target" or not-specified
// offset="#" (implements before, after, and index if no 'where')

DEFINE_GET_MEMBER(SkAdd);

SkAdd::SkAdd() : mode(kMode_indirect), 
    offset(SK_MaxS32), use(NULL), where(NULL) {
}

SkDisplayable* SkAdd::deepCopy(SkAnimateMaker* maker) {
    SkDrawable* saveUse = use;
    SkDrawable* saveWhere = where;
    use = NULL;
    where = NULL;
    SkAdd* copy = (SkAdd*) INHERITED::deepCopy(maker);
    copy->use = use = saveUse;
    copy->where = where = saveWhere;
    return copy;
}

bool SkAdd::draw(SkAnimateMaker& maker) {
    SkASSERT(use);
    SkASSERT(use->isDrawable());
    if (mode == kMode_indirect)
        use->draw(maker);
    return false;
}

#ifdef SK_DUMP_ENABLED
void SkAdd::dump(SkAnimateMaker* maker) {
    dumpBase(maker);
    dumpAttrs(maker);
    if (where)
        SkDebugf("where=\"%s\" ", where->id);
    if (mode == kMode_immediate)
        SkDebugf("mode=\"immediate\" ");
    SkDebugf(">\n");
    SkDisplayList::fIndent += 4;
    int save = SkDisplayList::fDumpIndex;
    if (use)    //just in case
        use->dump(maker);
    SkDisplayList::fIndent -= 4;
    SkDisplayList::fDumpIndex = save;
    dumpEnd(maker);
}
#endif

bool SkAdd::enable(SkAnimateMaker& maker ) {
    SkDisplayTypes type = getType();
    SkDisplayList& displayList = maker.fDisplayList;
    SkTDDrawableArray* parentList = displayList.getDrawList();
    if (type == SkType_Add) {
        if (use == NULL) // not set in apply yet
            return true;
    }
    bool skipAddToParent = true;
    SkASSERT(type != SkType_Replace || where);
    SkTDDrawableArray* grandList SK_INIT_TO_AVOID_WARNING;
    SkGroup* parentGroup = NULL;
    SkGroup* thisGroup = NULL;
    int index = where ? displayList.findGroup(where, &parentList, &parentGroup,
        &thisGroup, &grandList) : 0;
    if (index < 0)
        return true;
    int max = parentList->count();
    if (where == NULL && type == SkType_Move)
        index = max;
    if (offset != SK_MaxS32) {
        index += offset;
        if (index > max) {
            maker.setErrorCode(SkDisplayXMLParserError::kIndexOutOfRange);
            return true;    // caller should not add
        }
    }
    if (offset < 0 && where == NULL)
        index += max + 1;
    switch (type) {
        case SkType_Add:
            if (offset == SK_MaxS32 && where == NULL) {
                if (use->isDrawable()) {
                    skipAddToParent = mode == kMode_immediate;
                    if (skipAddToParent) {
                        if (where == NULL) {
                            SkTDDrawableArray* useParentList;
                            index = displayList.findGroup(this, &useParentList, &parentGroup,
                                &thisGroup, &grandList);
                            if (index >= 0) {
                                parentGroup->markCopySize(index);
                                parentGroup->markCopySet(index);
                                useParentList->begin()[index] = use;
                                break;
                            }                               
                        }
                        *parentList->append() = use;
                    }
                }
                break;
            } else {
                if (thisGroup)
                    thisGroup->markCopySize(index);
                *parentList->insert(index) = use;
                if (thisGroup)
                    thisGroup->markCopySet(index);
                if (use->isApply())
                    ((SkApply*) use)->setEmbedded();
            }
            break;
        case SkType_Move: {
            int priorLocation = parentList->find(use);
            if (priorLocation < 0)
                break;
            *parentList->insert(index) = use;
            if (index < priorLocation)
                priorLocation++;
            parentList->remove(priorLocation);
            } break;
        case SkType_Remove: {
            SkDisplayable* old = (*parentList)[index];
            if (((SkRemove*)(this))->fDelete) {
                delete old;
                goto noHelperNeeded;
            }
            for (int inner = 0; inner < maker.fChildren.count(); inner++) {
                SkDisplayable* child = maker.fChildren[inner];
                if (child == old || child->contains(old))
                    goto noHelperNeeded;
            }
            if (maker.fHelpers.find(old) < 0)
                maker.helperAdd(old);
noHelperNeeded:
            parentList->remove(index);
            } break;
        case SkType_Replace:
            if (thisGroup) {
                thisGroup->markCopySize(index);
                if (thisGroup->markedForDelete(index)) {
                    SkDisplayable* old = (*parentList)[index];
                    if (maker.fHelpers.find(old) < 0)
                        maker.helperAdd(old);
                }
            }
            (*parentList)[index] = use;
            if (thisGroup)
                thisGroup->markCopySet(index);
            break;
        default:
            SkASSERT(0);
    }
    if (type == SkType_Remove)
        return true;
    if (use->hasEnable())
        use->enable(maker);
    return skipAddToParent; // append if indirect: *parentList->append() = this;
}

bool SkAdd::hasEnable() const {
    return true;
}

void SkAdd::initialize() {
    if (use)
        use->initialize();
}

bool SkAdd::isDrawable() const {
    return getType() == SkType_Add && mode == kMode_indirect && offset == SK_MaxS32 &&
        where == NULL && use != NULL && use->isDrawable();
}

//SkDisplayable* SkAdd::resolveTarget(SkAnimateMaker& maker) {
//  return use;
//}


bool SkClear::enable(SkAnimateMaker& maker ) {
    SkDisplayList& displayList = maker.fDisplayList;
    displayList.clear();
    return true;
}


#if SK_USE_CONDENSED_INFO == 0

const SkMemberInfo SkMove::fInfo[] = {
    SK_MEMBER_INHERITED
};

#endif

DEFINE_GET_MEMBER(SkMove);

#if SK_USE_CONDENSED_INFO == 0

const SkMemberInfo SkRemove::fInfo[] = {
    SK_MEMBER_ALIAS(delete, fDelete, Boolean),  // !!! experimental
    SK_MEMBER(offset, Int),
    SK_MEMBER(where, Drawable)
};

#endif

DEFINE_GET_MEMBER(SkRemove);

SkRemove::SkRemove() : fDelete(false) {
}

#if SK_USE_CONDENSED_INFO == 0

const SkMemberInfo SkReplace::fInfo[] = {
    SK_MEMBER_INHERITED
};

#endif

DEFINE_GET_MEMBER(SkReplace);

