/**
 * @license
 * Copyright 2019 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.u2.view',
  name: 'AnyView',
  extends: 'foam.u2.View',

  requires: [
    'foam.u2.layout.Cols',
    'foam.u2.CheckBox',
    'foam.u2.DateTimeView',
    'foam.u2.TextField',
    'foam.u2.view.ArrayView',
    'foam.u2.view.ChoiceView',
    'foam.u2.view.MapView'
  ],

  constants: [
    {
      name: 'DEFAULT_TYPES',
      factory: function() {
        return [
          foam.u2.view.AnyView.Choice.create({
            label: '--',
            type: foam.Undefined,
            view: foam.u2.View,
            toType: function(o) {
              return undefined;
            }
          }),
          foam.u2.view.AnyView.Choice.create({
            label: 'String',
            type: foam.String,
            view: foam.u2.TextField,
            toType: function(o) {
              return o + '';
            }
          }),
          foam.u2.view.AnyView.Choice.create({
            label: 'Boolean',
            type: foam.Boolean,
            view: foam.u2.CheckBox,
            toType: function(o) {
              return !!o;
            }
          }),
          foam.u2.view.AnyView.Choice.create({
            label: 'Number',
            type: foam.Number,
            view: foam.u2.FloatView,
            toType: function(o) {
              return parseFloat(o) || 0;
            }
          }),
          foam.u2.view.AnyView.Choice.create({
            label: 'Map',
            type: foam.Object,
            view: foam.u2.view.MapView,
            toType: function(o) {
              return foam.Object.isInstance(o) ? o : {};
            }
          }),
          foam.u2.view.AnyView.Choice.create({
            label: 'FObject',
            type: foam.core.FObject,
            view: foam.u2.view.FObjectView,
            toType: function(o) {
              return foam.core.FObject.isInstance(o) ? o : foam.core.FObject.create();
            }
          }),
          foam.u2.view.AnyView.Choice.create({
            label: 'Array',
            type: foam.Array,
            view: foam.u2.view.ArrayView,
            toType: function(o) {
              return foam.Array.isInstance(o) ? o : [];
            }
          }),
          foam.u2.view.AnyView.Choice.create({
            label: 'Date',
            type: foam.Date,
            view: foam.u2.DateTimeView,
            toType: function(o) {
              if ( foam.Date.isInstance(o ) ) return o;
              return new Date(Date.parse(o) || Date.now());
            }
          })
        ];
      }
    }
  ],

  classes: [
    {
      name: 'Choice',
      properties: [
        {
          class: 'String',
          name: 'label'
        },
        {
          name: 'type'
        },
        {
          class: 'foam.u2.ViewSpec',
          name: 'view'
        },
        {
          class: 'Function',
          documentation: `
            A function that takes an argument and makes a best effort in
            converting that into the current type. See DEFAULT_TYPES for
            examples.
          `,
          name: 'toType'
        }
      ]
    }
  ],

  properties: [
    {
      name: 'types',
      factory: function() {
        return this.DEFAULT_TYPES;
      }
    },
    {
      name: 'selected',
      expression: function(data, types) {
        var type = foam.typeOf(data);
        var choice = types.find(t => type == t.type);
        if ( ! choice ) {
          console.warn("Unable to find view for type!");
          console.log(data);
        }
        return choice || types[0];
      }
    },
    {
      class: 'Boolean',
      name: 'enableChoice',
      value: true
    }
  ],

  methods: [
    function initE() {
      var self = this;
      this
        .start(self.Cols)
          .start()
            .style({flex: 1})
            .add(this.slot(function(selected) {
              return self.E()
              .tag(selected.view, {data: self.data});
            }))
          .end()
          .callIf(this.enableChoice, function() {
            this.start(self.ChoiceView, {
              choices$: self.types$.map(types => types.map(t => [t, t.label])),
              data$: self.selected$
            })
            .end()
          })
        .end();
    }
  ]
});

@@ -3860,177 +3860,263 @@
    .
-start()%0A            .style(%7Bflex: 1%7D)%0A            .add(this.slot(function(selected) %7B%0A              return self.E()%0A              .tag(selected.view, %7Bdata: self.data
+callIf(this.enableChoice, function() %7B%0A            this.start(self.ChoiceView, %7B%0A              choices$: self.types$.map(types =%3E types.map(t =%3E %5Bt, t.label%5D)),%0A              data$: self.selected$%0A            %7D)%0A            .style(%7B'margin-right': '8px'
 %7D)
-;
 %0A   
@@ -4124,18 +4124,34 @@
         
+.end()%0A          
 %7D
-)
 )%0A      
@@ -4147,35 +4147,37 @@
   %7D)%0A          .
-end
+start
 ()%0A          .ca
@@ -4177,47 +4177,27 @@
     
-.callIf(this.enableChoice, function() %7B
+  .style(%7Bflex: 1%7D)
 %0A   
@@ -4209,132 +4209,109 @@
     
+.add(
 this.s
-tart(self.ChoiceView, %7B%0A              choices$: self.types$.map(types =%3E types.map(t =%3E %5Bt, t.label%5D)),%0A              
+lot(function(selected) %7B%0A              return self.E()%0A              .tag(selected.view, %7B
 data
@@ -4314,33 +4314,32 @@
 data$: self.
-selected$
+data$%7D);
 %0A           
@@ -4333,35 +4333,34 @@
 ;%0A            %7D)
+)
 %0A
-  
           .end()
@@ -4356,37 +4356,24 @@
      .end()%0A
-          %7D)%0A
         .end

Fix AnyView which wasn't updating data.