function traverse(schema, rootName, cb) {
    function innerTraverse(schemaNode, path, noCallback) {
        if (!noCallback) {
            cb(path, schemaNode);
        }

        if (schemaNode.items) {
            if (schemaNode.items.anyOf) {
                schemaNode.items.anyOf.forEach(itemSchema => {
                    let typeValue = itemSchema.properties
                        && itemSchema.properties.type
                        && itemSchema.properties.type.default;
                    if (typeValue) {
                        innerTraverse(
                            itemSchema,
                            path ? (path + '-' + typeValue.replace(/'/g, '')) : typeValue,
                            false
                        );
                    }
                });
            }
            else {
                innerTraverse(schemaNode.items, path, true);
            }
        }
        else if (schemaNode.properties) {
            for (let propName in schemaNode.properties) {
                innerTraverse(
                    schemaNode.properties[propName],
                    path ? (path + '.' + propName) : propName,
                    false
                );
            }
        }

        // Or it's a leaf node.
    }

    innerTraverse(schema.option, rootName, false);
};

module.exports.traverse = traverse;


function convertToTree(rootSchema, rootNode) {

    function createNodeBase(schema) {
        let schemaType = schema.type;
        // Simplify type
        if (schemaType instanceof Array && schemaType.length === 1) {
            schemaType = schemaType[0];
        }
        let nodeBase = {};

        // Get type from default if possible. Reduce size.
        if (schema.default == null || typeof schema.default !== schemaType) {
            nodeBase.type = schemaType;
        }

        if (schema.default != null) {
            nodeBase.default = schema.default;
        }
        if (schema.items) {    // Array also may has properties.
            nodeBase.isArray = true;
        }
        else if (schema.properties && Object.keys(schema.properties).length) {
            nodeBase.isObject = true;
        }
        return nodeBase;
    }

    function createArrayItemNode(schema, parentNode) {
        let childNode = createNodeBase(schema, parentNode);
        if (schema.properties && schema.properties.type && schema.properties.type.default) {
            childNode.arrayItemType = schema.properties.type.default.replace(/'/g, '');
        }
        else {
            console.error('schema', schema);
            throw new Error('Some thing wrong happens');
        }
        return childNode;
    }
    function createPropertyNode(propName, schema, parentNode) {
        let childNode = createNodeBase(schema, parentNode);
        childNode.prop = propName;
        return childNode;
    }
    function processObjectType(currentSchema, currentNode) {
        if (!currentSchema.properties) {
            return;
        }
        let children = [];
        for (let propName in currentSchema.properties) {
            let childSchema = currentSchema.properties[propName];
            let childNode = createPropertyNode(propName, childSchema, currentNode);
            processRecursively(childSchema, childNode);
            children.push(childNode);
        }
        if (children.length) {
            currentNode.children = children;
        }
    }

    function processArrayType(currentSchema, currentNode) {
        if (!currentSchema.items) {
            return;
        }
        // Each item of array may have different type of object.
        // Like series, visualMap, legend
        if (currentSchema.items.anyOf) {
            let children = [];
            currentSchema.items.anyOf.forEach(itemSchema => {
                let childNode = createArrayItemNode(itemSchema, currentNode);
                processRecursively(itemSchema, childNode);
                children.push(childNode);
            });
            currentNode.children = children;
        }
        // Each item of array only have one type of object.
        // Like data and most of the compoents.
        else {
            processObjectType(
                currentSchema.items, currentNode
            );
        }
    }

    function processRecursively(currentSchema, currentNode) {
        // Array also may has properties.
        if (currentSchema.items) {
            processArrayType(currentSchema, currentNode);
        }
        else if (currentSchema.properties) {
            processObjectType(currentSchema, currentNode);
        }
        return currentNode;
    }

    return processRecursively(
        rootSchema, rootNode, 0
    );
};

module.exports.extractOptionKeys = function (schema) {
    const keysRepeatCount = {};
    const keysList = [];
    traverse(schema, '', (schemaPath, schemaNode) => {
        if (!schemaPath) {
            return;
        }
        const leafKey = schemaPath.split(/[\.-]/g).pop();
        if (keysRepeatCount[leafKey] == null) {
            keysRepeatCount[leafKey] = 0;
            keysList.push(leafKey);
        }
        keysRepeatCount[leafKey]++;
    });
    return keysList.map(key => {
        return {
            name: key,
            count: keysRepeatCount[key]
        };
    }).sort((a, b) => b.count - a.count);
};

// Partion the descriptions by the first part of path. For example
// { "title.label", "series-line.data", "series-bar.data" }
// Will be
// {
//   "title": { "label" },
//   "series-line": {"data"},
//   "series-bar": {"data"}
// }
module.exports.extractDesc = function (schema, docName) {
    let descriptionsMap = {};
    let propWithUIControlCount = 0;
    let propTotalCount = 0;
    traverse(schema, docName, (schemaPath, schemaNode) => {
        if (schemaNode.description) {
            // Extract component level path
            let parts = schemaPath.split('.');
            let divider = parts.length > 2 ? 2 : 1;
            let partionKey = parts.slice(0, divider).join('.');
            let subKey = parts.slice(divider).join('.');

            descriptionsMap[partionKey] = descriptionsMap[partionKey] || {};
            descriptionsMap[partionKey][subKey] = {
                desc: schemaNode.description,
                exampleBaseOptions: schemaNode.exampleBaseOptions,
                uiControl: schemaNode.uiControl
            };

            propTotalCount++;
            if (schemaNode.uiControl) {
                propWithUIControlCount++;
            }
        }
    });

    console.log(`Options with UIControl ${propWithUIControlCount} / ${propTotalCount} (${propWithUIControlCount/propTotalCount})`);

    return {
        outline: convertToTree(schema.option, {}),
        descriptions: descriptionsMap
    };
};