/*
const element = document.querySelector("OPTION");
element.addEventListener("mouseover", () => {});
element.addEventListener("mouseout", () => {});
*/

/*KEEP defaultName together in single file w/ character-info component*/
const DEFAULTNAME = "A Kindred That Is Not To Be Named";
/* function for using string length in display
https://downloads.teradata.com/blog/jasonstrimpel/2011/11/javascript-string-length-and-internationalizing-web-applications*/
(function () {
    var M = '\u0300-\u036F\u0483-\u0489\u0591-\u05BD ... \uFE20-\uFE26',
        regex = new RegExp('[' + M + ']', 'g');
     
    String.prototype.charCount = function () {
        var len = this.length, i = 0, count = len;
 
        for (i; i<len; i++) {
            if (regex.test(this[i])) 
                count--;
        }
 
        return count;  
    }     
}());

const app = Vue.createApp({
  data() {
    return {
      biography: {
        name: "",
        defaultName: DEFAULTNAME,/*make a set of names and randomly pick a default on page load*/
        age: null, /*why not age=0? bcuz if you use a value then placeholder does not apply in input box*/
        clan: null,
        generation: null,
        faction: null,
      },
      skillDistributions:[
        { 
          id: "Balanced",
          resource: [12,7,5,3,0,0]
        },
        { 
          id: "Jack-of-all-trades",
          resource: [8,10,8,1,0,0]
        },
        { 
          id: "Specialist",
          resource: [17,3,3,3,1,0]
        },
      ],
      clans :[
        {
          id: "Thin-blood",
          abilities: null,
          bloodPotency: "=0",
        },{
          id: "Caitiff",
          abilities: null,
          bloodPotency: ">0"
        },{
          id: "Brujah",
          abilities: ["Celerity", "Potence", "Presence"],
          bloodPotency: ">0"
        },{
          id: "Gangrel",
          abilities: ["Animalism", "Fortitude", "Protean"],
          bloodPotency: ">0"
        },{
          id: "Malkavian",
          abilities: ["Auspex", "Dominate", "Obfuscate"],
          bloodPotency: ">0"
        },{
          id: "Nosferatu",
          abilities: ["Animalism", "Obfuscate", "Potence"],
          bloodPotency: ">0"
        },{
          id: "Toreador",
          abilities: ["Celerity", "Potence", "Presence"],
          bloodPotency: ">0"
        },{
          id: "Tremere",
          abilities: ["Animalism", "Blood Sorcery", "Dominate"],
          bloodPotency: ">0"
        },{
          id: "Ventrue",
          abilities: ["Dominate", "Fortitude", "Presence"],
          bloodPotency: ">0"
        },
      ],
      attributes: {
        id: 'Attributes',
        resource: [
          0, 1, 4, 3, 1, 0,
        ] /*vtm5e attribute distribution: 1 times 4 dots; 3 times 3 dots, 4 times 2 dots
        sum of values in resource <= amount of values in section*/,
        data: [
          {
            id: 'Physical',
            list: [
              {
                id: 'Strength',
                value: 1,
              },
              {
                id: 'Dexterity',
                value: 1,
              },
              {
                id: 'Stamina',
                value: 1,
              },
            ],
          },
          {
            id: 'Social',
            list: [
              {
                id: 'Charisma',
                value: 1,
              },
              {
                id: 'Manipulation',
                value: 1,
              },
              {
                id: 'Composure',
                value: 1,
              },
            ],
          },
          {
            id: 'Mental',
            list: [
              {
                id: 'Intelligence',
                value: 1,
              },
              {
                id: 'Wits',
                value: 1,
              },
              {
                id: 'Resolve',
                value: 1,
              },
            ],
          },
        ],
      },
      skills: {
        id: 'Skills',
        resource: [12, 7, 5, 3, 0, 0],
        data: [
          {
            id: 'Physical',
            list: [
              {
                id: 'Athlethics',
                value: 0,
              },
              {
                id: 'Brawl',
                value: 0,
              },
              {
                id: 'Craft',
                value: 0,
              },
              {
                id: 'Drive',
                value: 0,
              },
              {
                id: 'Firearms',
                value: 0,
              },
              {
                id: 'Larceny',
                value: 0,
              },
              {
                id: 'Melee',
                value: 0,
              },
              {
                id: 'Stealth',
                value: 0,
              },
              {
                id: 'Survival',
                value: 0,
              },
            ],
          },
          {
            id: 'Social',
            list: [
              {
                id: 'Animal Ken',
                value: 0,
              },
              {
                id: 'Etiquette',
                value: 0,
              },
              {
                id: 'Insight',
                value: 0,
              },
              {
                id: 'Intimidation',
                value: 0,
              },
              {
                id: 'Leadership',
                value: 0,
              },
              {
                id: 'Performance',
                value: 0,
              },
              {
                id: 'Persuasion',
                value: 0,
              },
              {
                id: 'Streetwise',
                value: 0,
              },
              {
                id: 'Subterfuge',
                value: 0,
              },
            ],
          },
          {
            id: 'Mental',
            list: [
              {
                id: 'Academics',
                value: 0,
              },
              {
                id: 'Awareness',
                value: 0,
              },
              {
                id: 'Finance',
                value: 0,
              },
              {
                id: 'Investigation',
                value: 0,
              },
              {
                id: 'Medicine',
                value: 0,
              },
              {
                id: 'Occult',
                value: 0,
              },
              {
                id: 'Politics',
                value: 0,
              },
              {
                id: 'Science',
                value: 0,
              },
              {
                id: 'Technology',
                value: 0,
              },
            ],
          },
        ],
      },
      disciplines:{
        id: "Disciplines",
        resource: [0,1,1,0,0,0],
        data: [
          {
            id: 'Animalism',
            value: 0,
          },
          {
            id: 'Auspex',
            value: 0,
          },
          {
            id: 'Blood Sorcery',
            value: 0,
          },
          {
            id: 'Celerity',
            value: 0,
          },
          {
            id: 'Dominate',
            value: 0,
          },
          {
            id: 'Fortitude',
            value: 0,
          },
          {
            id: 'Obfuscate',
            value: 0,
          },
          {
            id: 'Potence',
            value: 0,
          },
          {
            id: 'Presence',
            value: 0,
          },
          {
            id: 'Protean',
            value: 0,
          },
          
        ],
      },
    };
  },
});

app.component('sheet', {
  props: ['attr', 'skills','bio', 'clans' ,'distributions','disciplines'],
  data(){
    return{
      activeElements: []
    };
  },
  computed:{
    clan(){
      var i;
      for (i=0;i<this.clans.length; i++) if (this.clans[i].id===this.bio.clan) return i;
      return -1;
    }
  },
  methods:{
    handleActivate(activeElement){
console.log(activeElement)
      debugger;
      if (activeElement[0]) this.activeElements.push(activeElement[1]);
      else this.activeElements.splice(this.activeElements.indexOf(activeElement[1]) ,1);
    }
  },
  template: `
    <character-info
      :bio="bio"
      :clans="clans"
      :skills="skills"
      :distributions="distributions"
      @activate="handleActivate($event)">
    </character-info>
    <stat-section 
      :stats="attr"
      :activate="activeElements">
    </stat-section>
    <stat-section 
      :stats="skills"
      :activate="activeElements">
    </stat-section>
    <discipline-section 
      v-if="clan > -1"
      :stats="disciplines"
      :clan = "clans[clan]"
      :activate="activeElements">
    </discipline-section>`
});

/*NOTE
  maybe make resource into its own json
  resource: {attrs: array, skills: array, disciplines:array}
  and then use it as read-only props for stat section and pass the json to bio section
  */


app.component('stat-section', {
  props: ['stats', 'activate'],
  data() {
    return {
      resourceCount: null,
    };
  },

  watch:{
    'stats.resource':  {
      deep:true,
      handler(newVal,oldVal){
        this.resourceCount.forEach((element, index) => this.resourceCount[index] = newVal[index] + element - oldVal[index]);
      }
    }
  },

  /**
   * Counts values in stats.data, same format as stats.resource
   *
   * @param {Number} stats.resource Amount of dots you can allocate
   * @param {JSON} stats.data Current values
   * @param {Array} of numbers resourceCount - restricting how many stats can have array index values, for example:
   * [ 0, -8, 4, 3, 1, 0 ]
   * first zero - we can have 0 attributes with value 0
   * -8 - we can have only 1 attribute with value 1 and there are 9 attributes with value 1 currently
   * 4 - we can have 4 attributes with value 2 and there are zero allocated
   * 3 - we can have 3 attrs with value 3
   * ...
   */
  created() {
    let tmp = Array(this.stats.resource.length).fill(0);
    for (var i = 0; i < this.stats.data.length; i++) {
      for (var j = 0; j < this.stats.data[i].list.length; j++) {
        tmp[this.stats.data[i].list[j].value]++;
      }
    }
    tmp.forEach(
      (element, index) => (tmp[index] = this.stats.resource[index] - element)
    );
    this.resourceCount = tmp;
  }, //TODO DELETE {{activate}}
  template: `   {{activate}}
    <div class="statSection">
      <h2>{{stats.id}}</h2>
      <div class="resourceCount">{{resourceCount}}</div>
      <stat-category 
        v-for="list in stats.data"
        :key="list.id"
        :categ="list"
        :resource="this.resourceCount"
        :scale="stats.resource.length - 1"
        :activate="activate">
      </stat-category>
    </div>`
});
app.component('discipline-section', {
  props: ['stats','clan','blood-potency', 'activate'],
  
  data() {
    return {
      resourceCount: null,
    };
  },

  watch:{
    'stats.resource':  {
      deep:true,
      handler(newVal,oldVal){
        this.resourceCount.forEach((element, index) => this.resourceCount[index] = newVal[index] + element - oldVal[index]);
      }
    }
  },

  /**
   * Counts values in stats.data, same format as stats.resource
   *
   * @param {Number} stats.resource Amount of dots you can allocate
   * @param {JSON} stats.data Current values
   * @param {Array} of numbers resourceCount - restricting how many stats can have array index values, for example:
   * [ 0, -8, 4, 3, 1, 0 ]
   * first zero - we can have 0 attributes with value 0
   * -8 - we can have only 1 attribute with value 1 and there are 9 attributes with value 1 currently
   * 4 - we can have 4 attributes with value 2 and there are zero allocated
   * 3 - we can have 3 attrs with value 3
   * ...
   * doesnt work for disciplines due to format...
   */
  created() {
    let tmp = Array(this.stats.resource.length).fill(0);
    for (var i = 0; i < this.stats.data.length; i++) {
      tmp[this.stats.data[i].value]++;
    }
    tmp.forEach(
      (element, index) => (tmp[index] = this.stats.resource[index] - element)
    );
    this.resourceCount = tmp;
  },
  
  methods:{
    isPrimary(discipline){
      if (!this.clan.abilities) return false;
      for (var i = 0; i< this.clan.abilities.length; i++) if (discipline.id == this.clan.abilities[i]) return true;
      return false;
    }
  },
  
  
  template: `   
    <div class="statSection">
      <h2>{{stats.id}}</h2>
      <div class="resourceCount">{{resourceCount}}</div>
      <div class="statList">
        <h2>Primary</h2>
        <ul class="ulStats">
          <li 
            v-for="item in stats.data"
            :key="item.id">
            <stat v-show = "isPrimary(item)"
              :stat="item"
              :resource="resourceCount"
              :scale="stats.resource.length - 1"
              :activate="activate">
            </stat>
          </li>
        </ul>
      </div>
      <div 
        class="statList"
        :style = "{float:'right'}">
        <h2>Secondary</h2>
        <ul class="ulStats">
          <li 
            v-for="item in stats.data"
            :key="item.id">
            <stat v-show = "!isPrimary(item)"
              :stat="item"
              :resource="resourceCount"
              :scale="stats.resource.length - 1"
              :activate="activate"
              :disabled="(clan.abilities) ? true : false">
            </stat>
          </li>
        </ul>
      </div>
    </div>`
});

/*TODO 
  *make verification for age to block input of more than 4 chars
  *tooltips for generation in relation to age
  *implement blood potency for clan selection; based on generation
  *implement discipline resource in clan selection+potency ie [8,1,1,0,0,0] for non-thin-blood and [10,0,0,0,0,0] otherwise
  *implement factions
  *implement faction lock = once you pick faction your clan is locked to faction selected clans (user can select -none- option?)
  */
/*
mounted() {
  this.$el.addEventListener('mouseover', this.onMouseOver);
},
destroyed() {
  this.$el.removeEventListener('mouseleave', this.onMouseLeave);
}
*/

/*
	  @mouseover="$emit('mouseover', $event.target.checked)"
	  @mouseleave="$emit('mouseleave', $event.target.checked)"

          @mouseover = "abilitiesHover(true, clan)"
          @mouseleave = "abilitiesHover(false, clan)"
*/
app.component('character-info-option', {
  props: ['key', 'clan'],
  model: {
    event: ['mouseover', 'mouseleave']
  },
  methods:{
    abilitiesHover(isActive, target){
var opt = target.options[target.selectedIndex];
var value = opt ? opt.value : null;
console.log(isActive, value)
//      console.log('activate '+ isActive + ' ' + clan.abilites)
//      this.$emit('activate',[isActive, clan.abilities[0]]);
    }
  },
  template: `
        <option 
          @mouseover = "abilitiesHover(true, clan)"
          @mouseleave = "abilitiesHover(false, clan)"
	>{{clan.id}}
        </option>
`
});

app.component('character-info', {
  emits: ['activate'],
  props: ['bio', 'clans','distributions','skills'],
  computed:{
    nameBoxWidth(){
      let correction = 1 + this.bio.name.length/15; //TODO width does not seem to handle strings alternating space and letter eg. 'A B C D E F' TODO https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/@@matchAll
      let tmp = (this.bio.name.length>0) ? this.bio.name.charCount() + correction : this.bio.defaultName.charCount()+3;
      return tmp;
    }
  },
  methods:{
    abilitiesHover(isActive, target){
var opt = target.options[target.selectedIndex];
var value = opt ? opt.value : null;
console.log(isActive, value)
//      console.log('activate '+ isActive + ' ' + clan.abilites)
//      this.$emit('activate',[isActive, clan.abilities[0]]);
    }//,
//    handleActivate(event){
  //    console.log('XXactivate ')
    //},
  },
//<!-- abilitiesHover(true, clan)" -->
  template: `
    <div class="char-info">
      <input 
        class="heading1"
        :style="{width: nameBoxWidth + 'ch'}"
        type="text"
        v-model="bio.name" 
        :placeholder="bio.defaultName"
        />
      <b>Age:</b>
      <input
        :style= "{width: 7 + 'ch'}"
        v-model="bio.age"
        type="number"
        :placeholder = '123'/>
      <b>Generation:</b>
      <select 
        v-model="bio.generation">
        <option disabled value=null>-none-</option>
        <option>15th</option>
        <option>14th</option>
        <option>13th</option>
      </select>
      <b>Clan:</b>
      <select v-model="bio.clan">
        <option disabled value="">Pick a Clan</option>
        <character-info-option
          v-for="clan in clans"
          :key = "clan.id"
          :clan="clan"
>
        </character-info-option>
      </select>
      <b>Faction:</b>
      <select v-model="bio.faction">
        <option disabled value="">Choose Your Coterie''s Faction</option>
        <option>Cammarilla</option>
        <option>etc</option>
        <option>C</option>
      </select>
      <b>Skills:</b>
      <select v-model="skills.resource">
        <option disabled value="">Select a distribution</option>
        <option 
          v-for="distrib in distributions"
          :key = "distrib.id"
          :value="distrib.resource">
          {{distrib.id}}
        </option>
      </select>
      
    </div>`,
});
/*
"$emit('activate',[false, clan.abilities[0]])"
@mouseover = "clan.abilities.forEach(element => $emit('activate',[true, element]))"
          @mouseleave = "clan.abilities.forEach(element =>$emit('activate',[false, element]))""**/
app.component('stat-category', {
  props: ['categ', 'resource', 'scale', 'activate'],
  template: `
    <div class="statList">
      <h2>{{categ.id}}</h2>
      <ul class="ulStats">
        <li 
          v-for="item in categ.list"
          :key="item.id">
          <stat 
            :stat="item"
            :resource="resource"
            :scale="scale"
            :activate="activate">
          </stat>
        </li>
      </ul>
    </div>`,
});

app.component('stat', {
  props: ['stat', 'resource', 'scale', 'disabled', 'activate'],
  data() {
    return {
      initialValue: this.stat.value,
      hoverPointer: null,
      isActive: false,
      isActivated : false,
    };
  },
  watch:{
    activate:{
      immediate:true,
      deep:true,
      handler(newVal,oldVal){
        this.isActivated = this.activate.includes(this.stat.id);
        this.isActive=this.isActivated;
      }
    }
  },
  methods: {
    /*TODO computed could be better instead of method */
    /**
     * Returns list of classes to add to point with value i
     *
     * @param {Number} i Value of processed point
     */
    pointClass(i) {
      return {
        point: true,
        init: i <= this.initialValue,
        fill: i > this.initialValue && i <= this.stat.value,
        active: this.hoverPointer && (i === this.hoverPointer || i > this.hoverPointer !== i > this.stat.value),
      };
    },
    /**
     * What to do when user clicks on point
     * - we check restriction if we can change value 
     * - if yes we save value to data
     * - we also modify resourceCount array
    */
    handleClick() {
      var new_value = this.hoverPointer;
      let tmp;
      const isAdd = new_value > this.stat.value;

      /**
       * Called when user clicks value higher than the current value of stat
       * Returns highest possible value that can be added
       *
       * @param {AvailableDots} array Amount of dots you can allocate
       * @param {ValueClicked} index
      */
      const addCheck = (array, index) => {
        var i;
        for (i = index; i >= 0; i--) {
          if (array[i] > 0) break;
        }
        return i;
      };
      
      //clicked empty point -> check if add is possible
      if (isAdd) {
        tmp = addCheck(this.resource, new_value);
        new_value = tmp > this.stat.value ? tmp : this.stat.value;
      }
      //clicked filled point -> removing points, not below limit aka initial value
      else if (new_value > this.initialValue) new_value--;
      
      //ERROR value add is disabled => only removal possible
      if (isAdd && this.disabled) return
      //OK setting values
      
      /*TODO
        https://v3.vuejs.org/style-guide/#implicit-parent-child-communication-use-with-caution
        consider using emits instead*/
      this.resource[this.stat.value] += 1;
      this.resource[new_value] += -1;
      this.stat.value = new_value;
    },
  },
  
  template: `  
    <div 
      :class="{stat : true, active : isActive}"
      @mouseover = "isActive = true;"
      @mouseleave = "if(!isActivated)isActive = false;">        
      <div class="statName">{{stat.id}}</div>
      <div class="points">  
        <span 
          v-for="i in scale"       
          :class="pointClass(i)"
          @click = "handleClick()" 
          @mouseover = "hoverPointer = i;"
          @mouseleave = "hoverPointer = null;"               
          :value = i>
        </span>          
      </div>             
    </div>`
});

const vm = app.mount('#root');


