Vue.component('characters-bar-item', {
    props: ['item', 'index'],
    template: `
      <a v-bind:href="'#' + escape(item.info.info.Name)"
               v-on:click="this.app_form.sheetImport(item);"
		style="margin-right: 5px;">
	{{ item.info.info.Name }}
    </a>`
  });

// ---

Vue.component('info-category', {
    props: ['group_id', 'category', 'category_index'],
    template: `
    <div class="AttributeClass">
    <table>
        <tr is="info-item"
            v-for="(item, index) in category.list"
            v-bind:group_id="group_id"
            v-bind:attr="item"
            v-bind:category_index="category_index"
            v-bind:category_id="category.id"
        ></tr>
    </table>
    </div>`
  });

Vue.component('info-item', {
    props: ['group_id', 'attr', 'category_index', 'category_id'],
    data: function() {
           return  {
	      for_id: 'field[' + this.category_id + '][' + this.attr.id + ']',
	   }},
    template: `
    <tr
>
        <td><label for="{{for_id}}">{{ attr.id }}</label></td>
        <td class="input"><input type="text" id="{{for_id}}" name="{{for_id}}"
		v-bind:value="attr.value"
                v-on:change=""
        ></td>
    </tr>`
  });

// ---

Vue.component('attribute-category', {
    props: ['group_id', 'category', 'category_index'],
    template: `
    <div class="AttributeClass">
    <h3>{{ category.id }} - {{category.priority}} - {{ category.sum }}</h3>
    <table>
        <tr is="attribute-item"
            v-for="(item, index) in category.list"
            v-bind:group_id="group_id"
            v-bind:attr="item"
            v-bind:category_index="category_index"
        ></tr>
    </table>
    </div>`
  });

Vue.component('attribute-item', {
    props: ['group_id', 'attr', 'category_index'],
    data: {
	hover_index: -1,
	hover_class: ''
    },
    methods: {
        getClass: function(index, attr_value) {
		return {
			'circle': true,
			'circleBlack': index<=attr_value,
			'circleGreen': this.hover_index>=0 && this.hover_index>attr_value && index>attr_value && index<=this.hover_index,
			'circleRed'  : this.hover_index>=0 && this.hover_index<=attr_value && index>=this.hover_index && index<=attr_value
			}
        },
        mouseOver: function(event) {
		this.hover_index = event.target.attributes.index.value * 1;
		this.$forceUpdate();
        },
        mouseOut: function(hover_index) {
            this.hover_index = -1;
		this.$forceUpdate();
        },
        setValue: function(attr, index) {
		var v, r;
		v = attr.value;
		v = v==index ? index-1 : index;
		if (isExist(attr.value_range))
			{
			r = attr.value_range;
			v = v<r[0] ? r[0] : v>r[1] ? r[1] : v;
			}
		v = v<r[0] ? r[0] : v>r[1] ? r[1] : v;
		attr.value = v;
                this.app_form.computeAttrSum(this.group_id, this.category_index);
                this.app_form.computeAttrPriorities(this.group_id, this.category_index);
        }
    },
    template: `
    <tr>
        <td><label>{{ attr.id }}</label></td>
        <td><label>{{ attr.value }}</label></td>
        <td><span>
            <span is="attribute-item-circle"
                v-for="index in 5" 
                v-bind:index=index
                v-bind:class="getClass(index, attr.value)"
                v-on:click="{setValue(attr, index)}"
                v-on:mouseover="mouseOver"
                v-on:mouseout="mouseOut"
            ></span>
        </td>

    </tr>`
  });

Vue.component('priority-item', {
    props: ['priority'],
    template: `
    <tr>
        <td>{{ priority.id }}</td>
        <td>{{ priority.value }}</td>
        <td>{{ priority.assignedTo }}</td>
    </tr>`
  });

// ---

Vue.component('skill-spell-category', {
    props: ['group_id', 'category', 'category_index'],
    template: `
    <div class="AttributeClass">
    <h3>{{ category.id }}</h3>
    <table>
        <tr is="skill-spell-item"
            v-for="(item, index) in category.list"
            v-bind:group_id="group_id"
            v-bind:attr="item"
            v-bind:category_index="category_index"
        ></tr>
    </table>
    </div>`
  });

Vue.component('skill-spell-item', {
    props: ['group_id', 'attr','category_index'],
    data: {
	hover_index: -1,
	hover_class: ''
    },
    methods: {
        getClass: function(index, attr_value) {
		return {
			'circle': true,
			'circleBlack': index<=attr_value,
			'circleGreen': this.hover_index>=0 && this.hover_index>attr_value && index>attr_value && index<=this.hover_index,
			'circleRed'  : this.hover_index>=0 && this.hover_index<=attr_value && index>=this.hover_index && index<=attr_value
			}
        },
        mouseOver: function(event) {
		this.hover_index = event.target.attributes.index.value * 1;
		this.$forceUpdate();
        },
        mouseOut: function(hover_index) {
            this.hover_index = -1;
		this.$forceUpdate();
        },
        setValue: function(attr, index) {
		var v, r;
		v = attr.value;
		v = v==index ? index-1 : index;
		if (isExist(attr.value_range))
			{
			r = attr.value_range;
			v = v<r[0] ? r[0] : v>r[1] ? r[1] : v;
			}
		attr.value = v;
        }
    },
    template: `
    <tr>
        <td><label>{{ attr.id }}</label></td>
        <td><label>{{ attr.value }}</label></td>
        <td>
            <div class="circle" 
                v-for="index in 5" 
                v-bind:index=index
                v-bind:class="getClass(index, attr.value)"
                v-on:click="{setValue(attr, index)}"
                v-on:mouseover="mouseOver"
                v-on:mouseout="mouseOut"
            ></div>
        </td>
    </tr>`
  });

// ---

const isExist = (ref)       => typeof ref != 'undefined' && ref!=null;
const isArray = (ref)       => typeof ref=='object' && ref!=null;
const isFunction = (ref)    => typeof ref=='function' && ref!=null;
const isObject = (ref)      => typeof ref=='object' && ref!=null;
const getValue = (ref, def) => isExist(ref) ? ref : def;

function cloneObject(obj)
	{
	return JSON.parse(JSON.stringify(obj));	//	return Object.assign({}, obj); - assign nefunguje spravne u parseru
	}

function cloneArray(arr)
	{
	return JSON.parse(JSON.stringify(arr));	//	return Object.assign({}, arr); - assign nefunguje spravne u parseru
	}

var app_form = new Vue({ 
    name: 'App form',
    el: '#app_form',
    data: function() {
        var data = {
            props: {},
       
            form_data: {},

            form_data_structure: {
                info: {
                    id: "header-id",
                    list: [
                        { id: "item-id", value: "" }
                    ]
                },
                attributes: {
                    id: "header-id",
                    list: [
                        { id: "item-id", value: 1, value_range: [1, 5] }
                    ],
                    priority: "C",
                    sum: 3
                },
                skills: {
                    id: "header-id",
                    list: [
                        { id: "item-id", value: 0 }
                    ],
                    sum: 0
                },
                spells: {
                    id: "header-id",
                    list: [
                        { id: "item-id", value: 0 }
                    ],
                    sum: 0
                }
	    }
	}
	data.props = config;	// load config
	// load blank sheet to structure
	var
	blank      = cloneObject(data.props.CharacterSheetBlank),
	structure  = cloneObject(data.form_data_structure);
	this.formdataParser(data.form_data, structure, blank);
        this.computeAttrAll(data.form_data);
    return data;
    },

    methods: {

        error: function (source, text) {
            console.log(['Error app_form', source].join('.') + ': ' + text); // document.getElementById('error').innerHTML()
        },

        computeAttrAll: function(data) {
            var data = isObject(data) ? data : this.form_data;
            var group_id, group, i, i_end;
            for (group_id in data)
                {
                group = data[group_id];
                i_end = group.length;
                for (i=0; i<i_end; i++)
                    {
                    if (isExist(group[i].sum))
                        {
                        this.computeAttrSum(group_id, i, data);
                        }
                    }
//console.log(JSON.stringify(group))
                    if (isExist(group[0].priority))
                        {
                        this.computeAttrPriorities(group_id, null, data);
                        }
                }
	},

        computeAttrSum: function(group_id, category_index, data) { 
            var data = isObject(data) ? data : this.form_data;
//console.log(JSON.stringify(data))
            var sum  = 0, category = data[group_id][category_index], list = category.list, len = list.length, i;
            for (i = 0; i < len; i++) {
                sum += parseInt(list[i].value);
            }
            category.sum = sum;
            return true;
        },

        computeAttrPriorities: function(group_id, category_index, data) {	//event, index
            var data  = isObject(data) ? data : this.form_data;
            var group = data[group_id], i, j, tmp, i_end;
            tmp = [];
            for (i in group)
                {
                tmp[i] = {sum: group[i].sum, order: i};
                i++;
                }
            tmp.sort( function(a, b) {return b.sum - a.sum;} );
            i_end = i;
            for (i=0; i<i_end; i++)
                {
                group[tmp[i].order].priority = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.charAt(i);
                }
        },

        sheetImport: function(imported_sheet) {
            var fn = 'sheetImport';
console.log(fn);
            var 
            sheet = isObject(imported_sheet) ? imported_sheet : {},
            blank = cloneObject(this.props.CharacterSheetBlank);
            this.sheetParser(blank, sheet);		// update blank-sheet by sheet
            this.formdataParser(this.form_data, this.form_data_structure, blank);	// update form-data
            this.computeAttrAll();
	},

        sheetParser: function (blank, sheet) {	// parse charactesr_sheet to list of [field_id, value]
            var fn, i;
            fn = 'sheetParser';
console.log(fn);
            if (!isObject(blank) || !isObject(sheet))
                {
                return;
                }
            for(i in blank)
                {
                if (!isObject(sheet) || !(i in sheet))
                    {
                    continue;
                    }
                if (isObject(blank[i]))	// object, repeat
                    {
                    if (!isObject(sheet[i]))
                        {
                        this.error(fn, 'Value in "parsed object" is not type Object.');
                        }
                    this.sheetParser(blank[i], sheet[i]);
                    }
                else
                    {
                    blank[i] = sheet[i];	// copy value
                    }
                }
        },

        formdataParser: function(out, structure, sheet) {	// parse sheet to form-data-structure
console.log('formdataParser');
            var i, j, k, jj, kk;
            for (i in structure)			// i = group / atributtes
                {
                if (!isObject(structure[i]) || !isObject(sheet[i]))
                    {
                    return;
                    }
                if (!isArray(out[i]))
                    {
                    out[i] = [];
                    }
//console.log('-- '+i+' --')
                jj = 0;
                for (j in sheet[i])			// j = category / physical
                    {
                    if (!isObject(sheet[i][j]))
                        {
                        return;
                        }
//console.log('-- '+j+' --')
                    if (!isObject(out[i][jj]))
                        {
                        out[i][jj] = cloneObject(structure[i]);
                        }
                    out[i][jj].id = j;							// copy group-id
                    if (isExist(structure[i].list) && (!isExist(out[i][jj].list) || !isArray(out[i][jj].list)))	// create plistriority, if not exist
                        {
                        out[i][jj].list = cloneObject(structure[i].list);
                        }
                    if (isExist(structure[i].sum) && !isExist(out[i][jj].sum))		// create sum, if not exist
                        {
                        out[i][jj].sum = structure[i].sum;
                        }
                    if (isExist(structure[i].priority) && !isExist(out[i][jj].priority))	// create priority, if not exist
                        {
                        out[i][jj].priority = structure[i].priority;
                        }
                    temp = cloneObject(structure[i].list[0]);
                    kk = 0;
                    for (k in sheet[i][j])
                        {
                        if (!isExist(out[i][jj].list[kk]))
                            {
                            out[i][jj].list[kk] = cloneObject(temp);
                            }
                         out[i][jj].list[kk].id    = k;
                         out[i][jj].list[kk].value = sheet[i][j][k];
                         kk++;
                        }
                    jj++;
                    }
            }

	}

//    created: function() {
//console.log('app-form created...');
//    },
//  mounted: function() {
//console.log('app-form mounted...');
//  },

        }



/*
//dataCreateNewStructure: function()
//	{
//	blank  = cloneObject(this.props.CharacterSheetBlank);
//	}

//formDataNew: function()
//	{
//	this.form_data = cloneObject(this.form_data_structure);
//	},

//formdataUpdateByBlankSheet: function()
//	{
//        this.sheetImport(this.props.CharacterSheetBlank);
//	},



exportParser(template, obj, out)	// parse charactesr_sheet to list of [field_id, value]
	{
	var i, fn, id;
	fn = 'exportParser';
	if (!isObject(obj))
		{
		return false;
		}
	for(i in template)
		{
//console.log('exportParser '+JSON.stringify(obj))
		if (isObject(template[i]))
			{
			this.exportParser(template[i], obj, out[i]);
			}
		else	{
			id = template[i];
			if (!(id in obj) || !isExist(obj[id].value))
				{
				this.error(fn, 'Field or Field.value not exist in character_fields. ' + String(id));
				return;
				}
			out[i] = obj[id].value;
			}
		}
	}

exportCharacterSheet(value)
	{
	var fn = 'exportCharacterSheet';
console.log(fn);
	var character_sheet  = cloneObject(this.props.config.CharacterSheetBlank);
	var character_fields = cloneObject(this.state.character_fields);
//console.log('exportCharacterSheet '+JSON.stringify(character_sheet))
	this.exportParser(this.props.config.parser_template, character_fields, character_sheet);
console.log('exportCharacterSheet ' + JSON.stringify(character_sheet));
	return;
	}
	},


*/
});
		






// https://beautifier.io/
