dP.Tag = {
  getOrCreate: function(val) {
    const matched = dP.Tag.getByName(val);

    if(matched)
      return matched;

    // create
    const tagID = ++dP.maxTagID,
      item = {
        id: tagID,
        name: val
      };

    dP.tagsHash[tagID] = item;
    dP.tags.push(item);

    return item;

  },
  remove: function(tagID) {
    dP.tags.splice(dP.tags.indexOf(dP.tagsHash[tagID]), 1);
    delete dP.tagsHash[tagID];
  },
  getByID: function(tagID) {
    return dP.tagsHash[tagID]
  },
  getByName: function(name) {
    return dP.tags.filter(a=>a.name === name)[0];
  },

  disconnectFromProduct: function(product, tag) {
    const tagID = tag.id;
    if(product.tags.indexOf(tagID) > -1){
      product.tags.splice( product.tags.indexOf(tagID), 1 );

      const connection = dP.connections
        .filter(connection =>
          connection.tag === tagID &&
          connection.type === 0 &&
          connection.eid === product.id
        )[0];

      if(!connection)
        return;

      if(connection.cid === dP.maxConnection-1)
        dP.maxConnection--;

      dP.connections.splice(
        dP.connections.indexOf(
          connection
        ) ,1);

      dP.Tag.removeIfNoConnections(tag);

      dP.slice.productTable.updateFilterCache(product);
    }
  },
  connectToProduct: function(product, tag) {
    const tagID = tag.id;

    if(product.tags.indexOf(tagID) === -1){
      product.tags.push( tagID );
      dP.connections.push({
        cid: ++dP.maxConnection,
        type: 0,
        eid: product.id,
        tag: tagID
      });

      dP.slice.productTable.updateFilterCache(product);

    }
  },

  removeIfNoConnections: function({tagID}) {

    if(dP.connections.filter(connection=>connection.tag === tagID).length === 0){
      dP.Tag.remove(tagID)
    }
  }
};