import SparqlAttribute from './SparqlAttribute'
import SparqlObject from '../SparqlObject/SparqlObject'
import { ConfigurationAttribute, Type } from '../Core/types'
import sparqljs from 'sparqljs'
import { isUri } from '../SparqlObject/common'


export function initialize(this: SparqlAttribute, confAttribute: ConfigurationAttribute = new ConfigurationAttribute(), sparqlObject: SparqlObject) {
    this.name = confAttribute.name;
    this.arrayable = confAttribute.arrayable;
    this.type = confAttribute.type || Type.LITTERAL;
    this.reference = confAttribute.reference || '';
    if (confAttribute.reference) this.type = Type.OBJECT;

    let out = 'SELECT * WHERE { ' + sparqlObject.coreDefinition + ' }'
    let parser = new sparqljs.Parser(
        sparqlObject.prefixes
    );
    let parsed_definition = parser.parse(out);
    parsePattern.call(this, <sparqljs.Pattern>parsed_definition);
}




function parseTriple(this: SparqlAttribute, triples: sparqljs.Triple[], optionalToggle = false) {
    triples.forEach((triple) => {
        [triple.subject, triple.predicate, triple.object]
            .forEach((str, index, triple) => {
                if (str.toString().match('^\\?' + this.name)) {
                    this.optional = optionalToggle;
                    this.triples.push(
                        triple.map((rdfTerm) => {
                            if (isUri(<string>rdfTerm)) {
                                return '<' + rdfTerm + '>'
                            } else {
                                return rdfTerm
                            }
                        }).join(' '));
                }
            });
    })
}
export default initialize;

// Optional Toggle spot the "splat" optionality of an attribute, which will be used to 
// first check for its existence in query operation involving it 
function parsePattern(this: SparqlAttribute, pattern: sparqljs.Pattern, optionalToggle = false) {
    switch (pattern.type) {
        case 'bgp':
            parseTriple.call(this, pattern.triples, optionalToggle);
            break;
        case 'optional':
        (<sparqljs.BlockPattern>pattern).patterns.forEach((_pattern) => {
            parsePattern.call(this, _pattern, true);
        });
        break;
        case 'group':
            (<sparqljs.BlockPattern>pattern).patterns.forEach((_pattern) => {
                parsePattern.call(this, _pattern, optionalToggle);
            });
            break;
        case 'query':
            (<sparqljs.Pattern[]>pattern.where).forEach((_pattern) => {
                parsePattern.call(this, _pattern, optionalToggle);
            });
            break;
    }
}