/**
 * @license
 * Copyright (c) 2017 Google Inc. All rights reserved.
 * This code may only be used under the BSD style license found at
 * http://polymer.github.io/LICENSE.txt
 * Code distributed by Google as part of this project is also
 * subject to an additional IP rights grant found at
 * http://polymer.github.io/PATENTS.txt
 */
'use strict';

defineParticle(({TransformationDomParticle}) => {
  return class Multiplexer extends TransformationDomParticle {
    constructor() {
      super();
      this._itemSubIdByHostedSlotId = new Map();
      this._connByHostedConn = new Map();
    }
    async setViews(views) {
      this.handleIds = {};
      let arc = await this.constructInnerArc();

      let hostedParticle = await views.get('hostedParticle').get();

      // Map all additional connections.
      let otherMappedViews = [];
      let otherConnections = [];
      let index = 2;
      for (let [connectionName, otherView] of views) {
        if (['list', 'hostedParticle'].includes(connectionName)) {
          continue;
        }
        otherMappedViews.push(`map '${await arc.mapHandle(otherView._proxy)}' as v${index}`);
        let hostedOtherConnectionName = hostedParticle.connections.find(conn => conn.type.equals(otherView.type)).name;
        otherConnections.push(`${hostedOtherConnectionName} <- v${index++}`);
        this._connByHostedConn.set(hostedOtherConnectionName, connectionName);
      }

      this.on(views, 'list', 'change', async e => {
        let listHandle = views.get('list');
        let list = await listHandle.toList();

        if (list.length > 0) {
          this.relevance = 0.1;
        }

        for (let [index, item] of list.entries()) {
          if (this.handleIds[item.id]) {
            let itemView = await this.handleIds[item.id];
            itemView.set(item);
            continue;
          }

          let itemViewPromise = arc.createHandle(listHandle.type.primitiveType(), 'item' + index);
          this.handleIds[item.id] = itemViewPromise;

          let itemView = await itemViewPromise;

          let hostedSlotName = [...hostedParticle.slots.keys()][0];
          let slotName = [...this.spec.slots.values()][0].name;

          let slotId = await arc.createSlot(this, slotName, hostedParticle.name, hostedSlotName);

          if (!slotId) {
            continue;
          }

          this._itemSubIdByHostedSlotId.set(slotId, item.id);


          let recipe = `
${this.serializeSchema(hostedParticle)}
recipe
  use '${itemView._id}' as v1
  ${otherMappedViews.join('\n')}
  slot '${slotId}' as s1
  ${hostedParticle.name}
    ${hostedParticle.connections[0].name} <- v1
    ${otherConnections.join('\n')}
    consume ${hostedSlotName} as s1
`;
          try {
            await arc.loadRecipe(recipe, this);
            itemView.set(item);
          } catch (e) {
            console.log(e);
          }
        }

        // Update props of all particle's views.
        this._updateAllViews(views, this.config);
      });
    }

    combineHostedModel(slotName, hostedSlotId, content) {
      let subId = this._itemSubIdByHostedSlotId.get(hostedSlotId);
      if (!subId) {
        return;
      }
      let items = this._state.renderModel ? this._state.renderModel.items : [];
      let listIndex = items.findIndex(item => item.subId == subId);
      let item = Object.assign({}, content.model, {subId});
      if (listIndex >= 0 && listIndex < items.length) {
        items[listIndex] = item;
      } else {
        items.push(item);
      }
      this._setState({renderModel: {items}});
    }

    combineHostedTemplate(slotName, hostedSlotId, content) {
      if (!this._state.template && !!content.template) {
        let template = content.template;
        // Replace hosted particle connection in template with the corresponding this particle connection names.
        // TODO: make this generic!
        this._connByHostedConn.forEach((conn, hostedConn) => {
          template = template.replace(new RegExp(`{{${hostedConn}.description}}`, 'g'), `{{${conn}.description}}`);
        });
        this._setState({template});
      }
    }
  };
});

@@ -1170,20 +1170,16 @@
 nnection
-Name
  = hoste
@@ -1246,23 +1246,57 @@
 w.type))
-.name;%0A
+;%0A        if (hostedOtherConnection) %7B%0A  
         
@@ -1341,17 +1341,18 @@
 nnection
-N
+.n
 ame%7D %3C- 
@@ -1362,24 +1362,26 @@
 index++%7D%60);%0A
+  
         this
@@ -1420,25 +1420,26 @@
 erConnection
-N
+.n
 ame, connect
@@ -1444,24 +1444,34 @@
 ctionName);%0A
+        %7D%0A
       %7D%0A%0A   

allow multiplexer only pass some of its connections to hosted particles