Polymer({

  is: 'polymer-d3',

  properties: {
    // List of available charts
    availableCharts: {
      type: Array,
      value: () => {
        return [{
          label: 'Stacked Bar Chart',
          icon: 'icons:accessibility',
          element: 'bar-chart',
          callBack: 'initStackedBarChart'
        }, {
          label: 'Grouped Bar Chart',
          icon: 'icons:cloud-circle',
          element: 'bar-chart',
          callBack: 'initGroupedBarChart'
        }, {
          label: 'Waterfall Chart',
          icon: 'icons:accessibility',
          element: 'bar-chart',
          callBack: 'initWaterfallChart'
        }, {
          label: 'Difference',
          icon: 'icons:rowing',
          element: 'bar-chart',
          callBack: 'initDiffrenceChart'
        }, {
          label: 'Pie Chart',
          icon: 'icons:content-cut',
          element: 'pie-chart',
          callBack: 'setPieSettings'
        }, {
          label: 'Heat Map',
          icon: 'icons:bug-report',
          element: 'bar-chart',
          callBack: 'setHeatMapSettings'
        }, {
          label: 'Area Chart',
          icon: 'icons:dns',
          element: 'area-chart',
          callBack: 'setAreaSettings'
        }, {
          label: 'Sankey Chart',
          icon: 'icons:check-circle',
          element: 'sankey-chart',
          callBack: 'setSankeySettings'
        }];
      }
    },
    // Object desctibing selected chart type
    selectedChart: {
      type: Object,
      value: () => { return {};}
    },
    selectedChartObj: {
      type: Object,
      value: () => { return {};}
    },
    // Flag to display settngs components
    settingsVisible: {
      type: Boolean,
      value: false
    },
    // Inputs
    externals: {
      type: Array,
      value: () => { return [];}
    },
    inputs: {
      type:Array,
      notify: true,
      value: () => {return [];}
    },
    // Data
    source: {
      type: Array,
      value: () => {return [];}
    },

    // settings
    settings: {
      type: Array,
      value: () => {return [];}
    },

    // State container
    stateContainer: {
      type: Object,
      value: () => {return {};}
    },

    editMode: {
      type: Boolean,
      value: true
    }
  },

  observers: [
    '_selectedChanged(selectedChart)',
    '_inputsChanged(inputs.*)',
    '_settingsChanged(settings.*)',
    '_modeObserver(editMode)'
  ],

  _modeObserver: function(editMode) {
    if (!editMode) {
      this.set('settingsVisible', false);
    }
  },

  _inputsChanged: function(i) {
    if (this.selectedChart && this.selectedChart.element) {
      this.$$(this.selectedChart.element).draw();
    }
  },

  _settingsChanged: function(setting) {
    // figureout a way to parse Object that has changed from path
    // And run the callBack in that object
    if (setting.path !== 'settings') {
      this.debounce('settignsChangedDebounce', () => {
        var changed = PolymerD3.utilities.parsePath(setting.path, setting.base);
        if (changed.callBack) {
          changed.callBack.call(this.selectedChartObj);
        } else {
          this.selectedChartObj.resize();
        }
      }, 200);
    }
  },

  _selectedChanged: function(selectedChart) {
    console.log(this);
    let elem;
    this.set('settingsVisible', true);
    if (!PolymerD3.utilities.isEmptyObject(selectedChart)) {
      this.$$('.chartHolder').innerHTML = '';
      elem = PolymerD3.utilities.attachElement.call(
        this,
        selectedChart.element,
        '.chartHolder',
        selectedChart.callBack
      );
      // Data and headers(externals) should come from parent
      // and should be set to new child element
      // elem.set('source');
      // elem.set('externals');

      // Gets settings object from newly attached chart
      this.set('settings', elem.area);
      this.set('inputs', elem.inputs);
      this.set('selectedChartObj', elem);
      elem.set('source', this.source);
    } else {
      console.info('Empyt Object');
    }
  },

  check: function() {
    console.log(this);
  },

  showSettings: function() {
    this.set('settingsVisible', !this.settingsVisible);
  },

  // Bootstraps element as per mode(view/edit)
  bootstrapCharts: function(config) {
    this.set('source', config.source);
    this.set('selectedChart', config.selectedChart);
    this.set('externals', config.externals);
    this.set('settings', config.settings);
    this.set('inputs', config.inputs);
    if (config.mode === 'edit') {
      // Edit mode settings
      this.set('editMode', true);
    } else {
      this.set('editMode', false);
    }
    // To set inputs to selected chart manually
    this.selectedChartObj.set('inputs', config.inputs);
    this.selectedChartObj.draw();
  }
});

@@ -4253,24 +4253,70 @@
 n(config) %7B%0A
+    // data and externals are always required%0A
     this.set
@@ -4317,22 +4317,25 @@
 is.set('
-source
+externals
 ', confi
@@ -4336,22 +4336,25 @@
  config.
-source
+externals
 );%0A    t
@@ -4367,91 +4367,198 @@
 t('s
-electedChart', config.selectedChart);%0A    this.set('externals', config.externals
+ource', config.source);%0A    if (config.mode === 'create') %7B%0A      // Fresh Polymer d3%0A      this.set('editMode', true);%0A    %7D else %7B%0A      this.set('selectedChart', config.selectedChart
 );%0A
+  
     
@@ -4592,32 +4592,34 @@
 .settings);%0A    
+  
 this.set('inputs
@@ -4637,24 +4637,26 @@
 nputs);%0A    
+ 
+ 
 if (config.m
@@ -4679,16 +4679,18 @@
 %7B%0A      
+  
 // Edit 
@@ -4705,24 +4705,26 @@
 tings%0A      
+ 
+ 
 this.set('ed
@@ -4735,32 +4735,34 @@
 de', true);%0A    
+  
 %7D else %7B%0A      t
@@ -4752,32 +4752,34 @@
  %7D else %7B%0A      
+ 
+ 
 this.set('editMo
@@ -4795,22 +4795,26 @@
 e);%0A    
+  
 %7D%0A    
+ 
+ 
 // To se
@@ -4849,16 +4849,18 @@
 anually%0A
+  
     this
@@ -4907,24 +4907,26 @@
 nputs);%0A    
+ 
+ 
 this.selecte
@@ -4943,16 +4943,22 @@
 draw();%0A
+    %7D%0A
   %7D%0A%7D);%0A

Create mode implemented