const fs = require('fs')
const path = require('path')

const root = path.resolve(__dirname, '..')
const targets = [
  'node_modules/element-ui/lib/element-ui.common.js',
  'node_modules/element-ui/lib/table-column.js',
  'node_modules/element-ui/packages/table/src/table-column.js',
  'node_modules/element-ui/lib/select.js',
  'node_modules/element-ui/lib/pagination.js',
  'node_modules/element-ui/lib/mixins/emitter.js',
  'node_modules/element-ui/src/mixins/emitter.js'
]

function patchContent (content) {
  const nextChildren = content
    .replace(
      /var children = this\.isSubColumn \? parent\.\$el\.children : parent\.\$refs\.hiddenColumns\.children;/g,
      "var children = this.isSubColumn\n      ? (parent && parent.$el ? parent.$el.children : [])\n      : (parent && parent.$refs && parent.$refs.hiddenColumns ? parent.$refs.hiddenColumns.children : []);"
    )
    .replace(
      /const children = this\.isSubColumn \? parent\.\$el\.children : parent\.\$refs\.hiddenColumns\.children;/g,
      "const children = this.isSubColumn\n      ? (parent && parent.$el ? parent.$el.children : [])\n      : (parent && parent.$refs && parent.$refs.hiddenColumns ? parent.$refs.hiddenColumns.children : []);"
    )
    .replace(
      /var children = this\.isSubColumn\s*\n\s*\? \(parent && parent\.\$el \? parent\.\$el\.children : null\)\s*\n\s*: \(parent && parent\.\$refs && parent\.\$refs\.hiddenColumns \? parent\.\$refs\.hiddenColumns\.children : null\);\s*\n\s*if \(!children\) \{\s*\n\s*return;\s*\n\s*\}/g,
      "var children = this.isSubColumn\n      ? (parent && parent.$el ? parent.$el.children : [])\n      : (parent && parent.$refs && parent.$refs.hiddenColumns ? parent.$refs.hiddenColumns.children : []);"
    )
    .replace(
      /const children = this\.isSubColumn\s*\n\s*\? \(parent && parent\.\$el \? parent\.\$el\.children : null\)\s*\n\s*: \(parent && parent\.\$refs && parent\.\$refs\.hiddenColumns \? parent\.\$refs\.hiddenColumns\.children : null\);\s*\n\s*if \(!children\) \{\s*\n\s*return;\s*\n\s*\}/g,
      "const children = this.isSubColumn\n      ? (parent && parent.$el ? parent.$el.children : [])\n      : (parent && parent.$refs && parent.$refs.hiddenColumns ? parent.$refs.hiddenColumns.children : []);"
    )

  const nextCommit = nextChildren
    .replace(
      /owner\.store\.commit\('insertColumn', this\.columnConfig, columnIndex, this\.isSubColumn \? parent\.columnConfig : null\);/g,
      "owner && owner.store && this.$el && children && children.length && columnIndex > -1 && owner.store.commit('insertColumn', this.columnConfig, columnIndex, this.isSubColumn && parent ? parent.columnConfig : null);"
    )
    .replace(
      /owner\.store\.commit\("insertColumn", this\.columnConfig, columnIndex, this\.isSubColumn \? parent\.columnConfig : null\);/g,
      "owner && owner.store && this.$el && children && children.length && columnIndex > -1 && owner.store.commit('insertColumn', this.columnConfig, columnIndex, this.isSubColumn && parent ? parent.columnConfig : null);"
    )
    .replace(
      /owner && owner\.store && owner\.store\.commit\('insertColumn', this\.columnConfig, columnIndex, this\.isSubColumn && parent \? parent\.columnConfig : null\);/g,
      "owner && owner.store && this.$el && children && children.length && columnIndex > -1 && owner.store.commit('insertColumn', this.columnConfig, columnIndex, this.isSubColumn && parent ? parent.columnConfig : null);"
    )
    .replace(
      /this\.owner\.store\.commit\('removeColumn', this\.columnConfig, this\.isSubColumn \? parent\.columnConfig : null\);/g,
      "this.owner && this.owner.store && this.$el && this.$el.parentNode && this.owner.store.commit('removeColumn', this.columnConfig, this.isSubColumn ? parent.columnConfig : null);"
    )
    .replace(
      /this\.owner\.store\.commit\("removeColumn", this\.columnConfig, this\.isSubColumn \? parent\.columnConfig : null\);/g,
      "this.owner && this.owner.store && this.$el && this.$el.parentNode && this.owner.store.commit('removeColumn', this.columnConfig, this.isSubColumn ? parent.columnConfig : null);"
    )
    .replace(
      /this\.owner && this\.owner\.store && this\.owner\.store\.commit\('removeColumn', this\.columnConfig, this\.isSubColumn \? parent\.columnConfig : null\);/g,
      "this.owner && this.owner.store && this.$el && this.$el.parentNode && this.owner.store.commit('removeColumn', this.columnConfig, this.isSubColumn ? parent.columnConfig : null);"
    )
    .replace(
      /this\.owner[^\n]*store\.commit\('removeColumn', this\.columnConfig, this\.isSubColumn \? parent\.columnConfig : null\);/g,
      "this.owner && this.owner.store && this.$el && this.$el.parentNode && this.owner.store.commit('removeColumn', this.columnConfig, this.isSubColumn ? parent.columnConfig : null);"
    )
    .replace(
      /this\.owner[^\n]*store\.commit\("removeColumn", this\.columnConfig, this\.isSubColumn \? parent\.columnConfig : null\);/g,
      "this.owner && this.owner.store && this.$el && this.$el.parentNode && this.owner.store.commit('removeColumn', this.columnConfig, this.isSubColumn ? parent.columnConfig : null);"
    )
    .replace(
      /this\.referenceElm = this\.\$parent\.\$refs\.reference\.\$el;/g,
      "this.referenceElm = this.$parent && this.$parent.$refs && this.$parent.$refs.reference ? this.$parent.$refs.reference.$el : null;"
    )
    .replace(
      /this\.\$parent\.popperElm = this\.popperElm = this\.\$el;/g,
      "this.popperElm = this.$el;\n    this.$parent && (this.$parent.popperElm = this.popperElm);"
    )
    .replace(
      /this\.minWidth = this\.\$parent\.\$el\.getBoundingClientRect\(\)\.width \+ \"px\";/g,
      "this.minWidth = this.$parent && this.$parent.$el ? this.$parent.$el.getBoundingClientRect().width + \"px\" : this.minWidth;"
    )

  const oldPaginationRender = `var template = h('div', { 'class': ['el-pagination', {
        'is-background': this.background,
        'el-pagination--small': this.small
      }] });
    var TEMPLATE_MAP = {
      prev: h('prev'),
      jumper: h('jumper'),
      pager: h('pager', {
        attrs: { currentPage: this.internalCurrentPage, pageCount: this.internalPageCount, pagerCount: this.pagerCount, disabled: this.disabled },
        on: {
          'change': this.handleCurrentChange
        }
      }),
      next: h('next'),
      sizes: h('sizes', {
        attrs: { pageSizes: this.pageSizes }
      }),
      slot: h('slot', [this.$slots.default ? this.$slots.default : '']),
      total: h('total')
    };
    var components = layout.split(',').map(function (item) {
      return item.trim();
    });
    var rightWrapper = h('div', { 'class': 'el-pagination__rightwrapper' });
    var haveRightWrapper = false;

    template.children = template.children || [];
    rightWrapper.children = rightWrapper.children || [];
    components.forEach(function (compo) {
      if (compo === '->') {
        haveRightWrapper = true;
        return;
      }

      if (!haveRightWrapper) {
        template.children.push(TEMPLATE_MAP[compo]);
      } else {
        rightWrapper.children.push(TEMPLATE_MAP[compo]);
      }
    });

    if (haveRightWrapper) {
      template.children.unshift(rightWrapper);
    }

    return template;`

  const newPaginationRender = `var TEMPLATE_MAP = {
      prev: h('prev'),
      jumper: h('jumper'),
      pager: h('pager', {
        attrs: { currentPage: this.internalCurrentPage, pageCount: this.internalPageCount, pagerCount: this.pagerCount, disabled: this.disabled },
        on: {
          'change': this.handleCurrentChange
        }
      }),
      next: h('next'),
      sizes: h('sizes', {
        attrs: { pageSizes: this.pageSizes }
      }),
      slot: h('slot', [this.$slots.default ? this.$slots.default : '']),
      total: h('total')
    };
    var components = layout.split(',').map(function (item) {
      return item.trim();
    });
    var rightWrapperChildren = [];
    var leftWrapperChildren = [];
    var haveRightWrapper = false;

    components.forEach(function (compo) {
      if (compo === '->') {
        haveRightWrapper = true;
        return;
      }
      var vnode = TEMPLATE_MAP[compo];
      if (!vnode) return;
      if (!haveRightWrapper) {
        leftWrapperChildren.push(vnode);
      } else {
        rightWrapperChildren.push(vnode);
      }
    });

    var children = leftWrapperChildren.slice();
    if (haveRightWrapper) {
      children.unshift(h('div', { 'class': 'el-pagination__rightwrapper' }, rightWrapperChildren));
    }

    return h('div', { 'class': ['el-pagination', {
      'is-background': this.background,
      'el-pagination--small': this.small
    }] }, children);`

  const nextPagination = nextCommit.replace(oldPaginationRender, newPaginationRender)

  return nextPagination
    .replace(
      /var name = child\.\$options\.componentName;/g,
      "if (!child || !child.$options) { return; }\n    var name = child.$options.componentName;"
    )
    .replace(
      /var name = parent\.\$options\.componentName;/g,
      "var name = parent && parent.$options ? parent.$options.componentName : null;"
    )
    .replace(
      /name = parent\.\$options\.componentName;/g,
      "name = parent && parent.$options ? parent.$options.componentName : null;"
    )
    .replace(/(this\.owner && this\.owner\.store && )+(this\.\$el && this\.\$el\.parentNode && this\.owner\.store\.commit\('removeColumn', this\.columnConfig, this\.isSubColumn \? parent\.columnConfig : null\);)/g, "this.owner && this.owner.store && this.$el && this.$el.parentNode && this.owner.store.commit('removeColumn', this.columnConfig, this.isSubColumn ? parent.columnConfig : null);")
}

let patchedCount = 0

for (const rel of targets) {
  const file = path.join(root, rel)
  if (!fs.existsSync(file)) {
    continue
  }

  const original = fs.readFileSync(file, 'utf8')
  const next = patchContent(original)

  if (next !== original) {
    fs.writeFileSync(file, next, 'utf8')
    patchedCount += 1
  }
}

if (patchedCount > 0) {
  console.log(`[patch-element-ui] patched files: ${patchedCount}`)
} else {
  console.log('[patch-element-ui] no changes (already patched or target not found)')
}
