ActionTimeline* ActionTimelineCache::loadAnimationActionWithContent(const std::string&fileName, const std::string& content)
{
    // if already exists an action with filename, then return this action
    ActionTimeline* action = _animationActions.at(fileName);
    if(action)
        return action;

    rapidjson::Document doc;
    doc.Parse<0>(content.c_str());
    if (doc.HasParseError()) 
    {
        CCLOG("GetParseError %s\n", doc.GetParseError());
    }

    const rapidjson::Value& json = DICTOOL->getSubDictionary_json(doc, ACTION);

    action = ActionTimeline::create();

    action->setDuration(DICTOOL->getIntValue_json(json, DURATION));
    action->setTimeSpeed(DICTOOL->getFloatValue_json(json, TIME_SPEED, 1.0f));

    int timelineLength = DICTOOL->getArrayCount_json(json, TIMELINES);
    for (int i = 0; i<timelineLength; i++)
    {
        const rapidjson::Value& dic = DICTOOL->getSubDictionary_json(json, TIMELINES, i);
        Timeline* timeline = loadTimeline(dic);

        if(timeline)
            action->addTimeline(timeline);
    }

    _animationActions.insert(fileName, action);

    return action;
}
ActionTimeline* ActionTimelineCache::createActionWithFlatBuffersForSimulator(const std::string& fileName)
{
    FlatBuffersSerialize* fbs = FlatBuffersSerialize::getInstance();
    fbs->_isSimulator = true;
    auto builder = fbs->createFlatBuffersWithXMLFileForSimulator(fileName);
    
    ActionTimeline* action = ActionTimeline::create();
    
    auto csparsebinary = GetCSParseBinary(builder->GetBufferPointer());
    auto nodeAction = csparsebinary->action();
    
    action = ActionTimeline::create();
    
    int duration = nodeAction->duration();
    action->setDuration(duration);
    
    float speed = nodeAction->speed();
    action->setTimeSpeed(speed);
    
    auto timeLines = nodeAction->timeLines();
    int timelineLength = timeLines->size();
    for (int i = 0; i < timelineLength; i++)
    {
        auto timelineFlatBuf = timeLines->Get(i);
        Timeline* timeline = loadTimelineWithFlatBuffers(timelineFlatBuf);
        
        if (timeline)
            action->addTimeline(timeline);
    }
    
    fbs->deleteFlatBufferBuilder();
    
    return action;
}
ActionTimeline* ActionTimelineCache::loadAnimationActionWithFlatBuffersFile(const std::string &fileName)
{
    // if already exists an action with filename, then return this action
    ActionTimeline* action = _animationActions.at(fileName);
    if (action)
        return action;
    
    std::string path = fileName;
    
    std::string fullPath = FileUtils::getInstance()->fullPathForFilename(fileName.c_str());
    
    CC_ASSERT(FileUtils::getInstance()->isFileExist(fullPath));
    
    Data buf = FileUtils::getInstance()->getDataFromFile(fullPath);
    
    auto csparsebinary = GetCSParseBinary(buf.getBytes());
    
    auto nodeAction = csparsebinary->action();    
    action = ActionTimeline::create();
    
    int duration = nodeAction->duration();
    action->setDuration(duration);
    float speed = nodeAction->speed();
    action->setTimeSpeed(speed);
    
    auto animationlist = csparsebinary->animationList();
    int animationcount = animationlist->size();
    for (int i = 0; i < animationcount; i++)
    {
        auto animationdata = animationlist->Get(i);
        AnimationInfo info;
        info.name = animationdata->name()->c_str();
        info.startIndex = animationdata->startIndex();
        info.endIndex = animationdata->endIndex();
        action->addAnimationInfo(info);
    }

    auto timelines = nodeAction->timeLines();
    int timelineLength = timelines->size();
    for (int i = 0; i < timelineLength; i++)
    {
        auto timelineFlatBuf = timelines->Get(i);
        Timeline* timeline = loadTimelineWithFlatBuffers(timelineFlatBuf);
        
        if (timeline)
            action->addTimeline(timeline);
    }
    
    _animationActions.insert(fileName, action);
    
    return action;
}
ActionTimeline* ActionTimelineCache::createActionWithFlatBuffersForSimulator(const std::string& fileName)
{
    FlatBuffersSerialize* fbs = FlatBuffersSerialize::getInstance();
    fbs->_isSimulator = true;
    auto builder = fbs->createFlatBuffersWithXMLFileForSimulator(fileName);
    
    ActionTimeline* action = ActionTimeline::create();
    
    auto csparsebinary = GetCSParseBinary(builder->GetBufferPointer());
    auto nodeAction = csparsebinary->action();
    
    action = ActionTimeline::create();
    
    int duration = nodeAction->duration();
    action->setDuration(duration);
    
    float speed = nodeAction->speed();
    action->setTimeSpeed(speed);
    
    auto animationlist = csparsebinary->animationList();
    int animationcount = animationlist->size();
    for (int i = 0; i < animationcount; i++)
    {
        auto animationdata = animationlist->Get(i);
        AnimationInfo info;
        info.name = animationdata->name()->c_str();
        info.startIndex = animationdata->startIndex();
        info.endIndex = animationdata->endIndex();
        action->addAnimationInfo(info);
    }

    auto timeLines = nodeAction->timeLines();
    int timelineLength = timeLines->size();
    std::multimap<std::string, cocostudio::timeline::Timeline*> properTimelineMap;// order the timelines depends property name
    for (int i = 0; i < timelineLength; i++)
    {
        auto timelineFlatBuf = timeLines->Get(i);
        Timeline* timeline = loadTimelineWithFlatBuffers(timelineFlatBuf);
        if (timeline)
        {
            properTimelineMap.insert(std::make_pair(timelineFlatBuf->property()->c_str(), timeline));
        }
    }

    for (const auto& properTimelinePair : properTimelineMap)
    {
        action->addTimeline(properTimelinePair.second);
    }
    fbs->deleteFlatBufferBuilder();
    return action;
}
ActionTimeline* ActionTimeline::clone() const
{
    ActionTimeline* newAction = ActionTimeline::create();
    newAction->setDuration(_duration);
    newAction->setTimeSpeed(_timeSpeed);

    for (auto timelines : _timelineMap)
    {
        for(auto timeline : timelines.second)
        {      
            Timeline* newTimeline = timeline->clone();
            newAction->addTimeline(newTimeline);
        }
    }

    return newAction;
}