package cn.axzo.msg.center.service.pending.response.v3;

import java.util.ArrayList;

import org.apache.commons.collections4.CollectionUtils;

import cn.axzo.msg.center.service.domain.CardUrlConfig;
import cn.axzo.msg.center.service.domain.card.AppVersionConfig;
import cn.axzo.msg.center.service.domain.card.StateImageConfig;
import cn.axzo.msg.center.service.pending.card.domain.CardElementConfig;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedButtonV3;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedCardStyle;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedCardUrl;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedGroupInfo;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedGroupV3;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedKV;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedModelV3;
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedTemplateV3;

/**
 * @author yanglin
 */
public class ParsedModelV3Walker {

    public static void walkDown(ParsedModelV3 model, ParsedModel3Visitor visitor) {
        if (model == null) return;
        visitor.visitModel(model);
        ParsedTemplateV3 template = model.getTemplate();
        if (template != null) {
            visitor.visitTemplate(template);
            visitCard(visitor, template);
            visitAppVersionConfig(visitor, template);
            visitCardExtField(visitor, template);
            visitStateImageConfig(visitor, template);
        }
        ParsedCardStyle cardStyle = model.getCardStyle();
        if (cardStyle != null) {
            visitor.visitCardStyle(cardStyle);
            visitCardElement(cardStyle, visitor);
            visitor.exitCardStyle(cardStyle);
        }
        for (ParsedGroupV3 group : new ArrayList<>(model.determineGroups()))
            visitGroup(visitor, group);
        for (ParsedButtonV3 button : new ArrayList<>(model.determineButtons()))
            visitButton(visitor, button);
        if (template != null)
            visitor.exitTemplate(template);
        visitor.exitModel(model);
    }

    private static void visitCardElement(ParsedCardStyle cardStyle,
                                         ParsedModel3Visitor visitor) {
        if (cardStyle.getElementConfigs() == null) return;
        for (CardElementConfig cfg : new ArrayList<>(cardStyle.getElementConfigs())) {
            visitor.visitCardStyleElement(cfg);
            visitor.exitCardStyleElement(cfg);
        }
    }

    private static void visitAppVersionConfig(ParsedModel3Visitor visitor,
                                              ParsedTemplateV3 template) {
        if (template.getAppVersionConfigs() == null) return;
        for (AppVersionConfig cfg : new ArrayList<>(template.getAppVersionConfigs())) {
            visitor.visitAppVersionConfig(cfg);
            visitor.exitAppVersionConfig(cfg);
        }
    }

    private static void visitCardExtField(ParsedModel3Visitor visitor,
                                          ParsedTemplateV3 template) {
        if (template.getCardExtFields() == null) return;
        for (CardElementConfig cfg : new ArrayList<>(template.getCardExtFields())) {
            visitor.visitTemplateCardExtField(cfg);
            visitor.exitTemplateCardExtField(cfg);
        }
    }

    private static void visitStateImageConfig(ParsedModel3Visitor visitor,
                                              ParsedTemplateV3 template) {
        if (CollectionUtils.isEmpty(template.getStateImageConfigs())) return;
        for (StateImageConfig cfg : new ArrayList<>(template.getStateImageConfigs())) {
            visitor.visitStateImageConfig(cfg);
            visitor.exitStateImageConfig(cfg);
        }
    }

    private static void visitCard(ParsedModel3Visitor visitor,
                                  ParsedTemplateV3 template) {
        if (template == null) return;
        CardUrlConfig cardUrlConfig = template.getCardUrlConfig();
        if (cardUrlConfig != null && cardUrlConfig.getUrlConfig() != null) {
            visitor.visitTemplateCardUrlConfig(cardUrlConfig.getUrlConfig());
            visitor.exitTemplateCardUrlConfig(cardUrlConfig.getUrlConfig());
        }
        ParsedCardUrl cardUrl = template.getCardUrl();
        if (cardUrl != null && cardUrl.getUrl() != null) {
            visitor.visitTemplateCardUrl(cardUrl.getUrl());
            visitor.exitTemplateCardUrl(cardUrl.getUrl());
        }
    }

    private static void visitGroup(ParsedModel3Visitor visitor, ParsedGroupV3 group) {
        visitor.visitGroup(group);
        ParsedGroupInfo groupInfo = group.getGroupInfo();
        if (groupInfo != null) {
            visitor.visitGroupInfo(group, groupInfo);
            visitGroupKeyValues(visitor, group, groupInfo);
            visitWorkerInfo(visitor, group);
            visitGroupDetailConfig(visitor, group, groupInfo);
            visitGroupDetail(visitor, group, groupInfo);
            visitor.exitGroupInfo(group, groupInfo);
        }
        visitor.exitGroup(group);
    }

    private static void visitWorkerInfo(ParsedModel3Visitor visitor,
                                        ParsedGroupV3 group) {
        if (group.getWorkerInfo() == null) return;
        visitor.visitGroupWorkerInfo(group, group.getWorkerInfo());
        visitor.exitGroupWorkerInfo(group, group.getWorkerInfo());
    }

    private static void visitGroupKeyValues(ParsedModel3Visitor visitor,
                                            ParsedGroupV3 group,
                                            ParsedGroupInfo groupInfo) {
        if (groupInfo.getKeyValues() == null) return;
        for (ParsedKV kv : new ArrayList<>(groupInfo.getKeyValues())) {
            visitor.visitGroupKeyValue(group, kv);
            if (kv.getPersonInfo() != null) {
                visitor.visitGroupKVPersonInfo(group, kv.getPersonInfo());
                visitor.exitGroupKVPersonInfo(group, kv.getPersonInfo());
            }
            if (kv.getPhoneInfo() != null) {
                visitor.visitGroupKVPhoneInfo(group, kv.getPhoneInfo());
                visitor.exitGroupKVPhoneInfo(group, kv.getPhoneInfo());
            }
            visitor.exitGroupKeyValue(group, kv);
        }
    }

    private static void visitGroupDetailConfig(ParsedModel3Visitor visitor,
                                               ParsedGroupV3 group,
                                               ParsedGroupInfo groupInfo) {
        if (groupInfo.getDetail() == null) return;
        visitor.visitGroupDetailConfig(group, groupInfo.getDetail());
        if (groupInfo.getDetail().getUrlConfig() != null) {
            visitor.visitGroupDetailUrlConfig(group, groupInfo.getDetail().getUrlConfig());
            visitor.exitGroupDetailUrlConfig(group, groupInfo.getDetail().getUrlConfig());
        }
        visitor.exitGroupDetailConfig(group, groupInfo.getDetail());
    }

    private static void visitGroupDetail(ParsedModel3Visitor visitor,
                                         ParsedGroupV3 group,
                                         ParsedGroupInfo groupInfo) {
        if (groupInfo.getParsedDetail() == null) return;
        visitor.visitGroupDetail(group, groupInfo.getParsedDetail());
        if (groupInfo.getParsedDetail().getUrl() != null) {
            visitor.visitGroupDetailUrl(group, groupInfo.getParsedDetail().getUrl());
            visitor.exitGroupDetailUrl(group, groupInfo.getParsedDetail().getUrl());
        }
        visitor.exitGroupDetail(group, groupInfo.getParsedDetail());
    }

    private static void visitButton(ParsedModel3Visitor visitor,
                                    ParsedButtonV3 button) {
        visitor.visitButton(button);
        if (button.getUrlConfig() != null) {
            visitor.visitButtonUrlConfig(button, button.getUrlConfig());
            visitor.exitButtonUrlConfig(button, button.getUrlConfig());
        }
        if (button.getUrl() != null) {
            visitor.visitButtonUrl(button, button.getUrl());
            visitor.exitButtonUrl(button, button.getUrl());
        }
        visitor.exitButton(button);
    }

}