﻿<template>
  <ui-property v-if="!isHidden" :field="config.field" :label="label" :hide-label="config.hideLabel || isStatic" :description="description" :required="config.required" :class="classList" :is-text="view === 'output'">
    <component v-if="fieldComponent" :is="fieldComponent" :config="config" :value="model" :entity="value" @input="onChange" :meta="meta" :disabled="isDisabled" :depth="depth" />
    <p v-if="config.helpText" class="ui-property-help" v-localize="config.helpText"></p>
  </ui-property>
</template>


<script>
  import Strings from 'zero/services/strings';
  import Objects from 'zero/services/objects';
  import Localization from 'zero/services/localization';

  const staticViews = ['line'];

  export default {
    name: 'uiEditorComponent',

    props: {
      value: {
        type: [ Object, Array ]
      },
      config: {
        type: Object,
        required: true,
        default: () =>
        {
          hidden: false
        }
      },
      renderer: {
        type: Object,
        default: () =>
        {
          return {};
        }
      },
      meta: {
        type: Object,
        default: () =>
        {
          return {};
        }
      },
      depth: {
        type: Number,
        default: 0
      },
      disabled: {
        type: Boolean,
        default: false
      }
    },

    watch: {
      value: {
        deep: true,
        handler: function ()
        {
          this.rebuildModel();
        }
      },
      config: {
        deep: true,
        handler: function ()
        {
          this.rebuildConfig();
        }
      },
      renderer: {
        deep: true,
        handler: function ()
        {
          this.rebuildConfig();
        }
      }
    },

    data: () => ({
      fieldComponent: null,
      model: null,
      selector: [],
      classList: [],
      label: null,
      description: null
    }),

    mounted()
    {
      this.rebuildModel();
    },

    computed: {
      view()
      {
        return this.config.display;
      },
      isHidden()
      {
        return this.config.hidden || (typeof this.config.condition === 'function' && !this.config.condition(this.value));
      },
      isDisabled()
      {
        return this.disabled || (typeof this.config.disabled === 'boolean' && this.config.disabled) || (typeof this.config.disabled === 'function' && this.config.disabled(this.value));
      },
      isStatic()
      {
        return staticViews.indexOf(this.config.display) > -1;
      }
    },

    created()
    {
      this.fieldComponent = () =>
      {
        if (this.view === 'custom')
        {
          if (this.config.path.indexOf('@zero') === 0)
          {
            return import(`zero/` + this.config.path.substring(6));
          }
          else if (this.config.path.indexOf('@shop') === 0) // TODO common system for plugins
          {
            return import(`shop/` + this.config.path.substring(6));
          }
          else
          {
            // TODO external imports
          }
        }
        else if (this.view === 'renderer')
        {
          return import(`zero/editor/editor`);
        }
        else if (this.isStatic)
        {
          return import(`zero/editor/fields/static/${this.view.toLowerCase()}`);
        }
        else
        {
          return import(`zero/editor/fields/${this.view.toLowerCase()}`);
        }
      }

      this.rebuildModel();
      this.rebuildConfig();
    },

    methods: {

      rebuildModel()
      {
        this.selector = Strings.selectorToArray(this.config.field);
        var currentValue = this.value;

        if (!this.selector || !this.selector.length || !currentValue)
        {
          this.model = null;
        }
        else
        {
          for (var key of this.selector)
          {
            if (key in currentValue)
            {
              currentValue = currentValue[key];
            }
            else
            {
              break;
            }
          }

          this.model = currentValue;
        }
      },


      rebuildConfig()
      {
        // build class list
        let classes = typeof this.config.class === 'string' ? this.config.class.split(' ') : (this.config.class || []);
        if (this.view === 'renderer' || this.view === 'nested')
        {
          classes.push('full-width');
        }
        if (this.depth > 0)
        {
          classes.push('is-nested');
        }
        if (this.isStatic)
        {
          classes.push('is-static');
        }
        this.classList = classes;


        // build label
        let label = null;
        if (this.config.label && this.config.label.indexOf('@') === 0)
        {
          label = this.config.label;
        }
        else if (this.renderer.labelTemplate)
        {
          label = this.renderer.labelTemplate(this.config.label || this.config.field);
        }
        else
        {
          label = this.config.label || this.config.field;
        }
        this.label = Localization.localize(label);


        // build description
        let description = null;
        if (this.config.description && this.config.description.indexOf('@') === 0)
        {
          description = this.config.description;
        }
        else if (this.config.description === null)
        {
          description = null;
        }
        else if (this.renderer.descriptionTemplate)
        {
          description = this.renderer.descriptionTemplate(this.config.description || this.config.field);
        }
        else
        {
          description = this.config.description;
        }
        this.description = Localization.localize(description, { hideEmpty: true });
      },


      onChange(value)
      {
        if (typeof value === 'function')
        {
          value(this.value);
        }
        else
        {
          Objects.setValue(this.value, this.selector, value);
        }
        this.$emit('input', this.value);
      }
    }
  }
</script>