const isDOM = (obj) => {
  return typeof HTMLElement === 'object'
    ? obj instanceof HTMLElement
    : obj &&
        typeof obj === 'object' &&
        obj.nodeType === 1 &&
        typeof obj.nodeName === 'string'
}
/* const extend = (obj, obj2) => {
  for (const k in obj2) {
    if (obj2.hasOwnProperty(k)) obj[k] = obj2[k]
  }
  return obj
} */
const isInBody = (node) => {
  return node === document.body ? false : document.body.contains(node)
}
const wrapperRefDom = (refDom) => {
  let prevDom = null
  let currDom = refDom
  if (!isInBody(currDom)) return currDom

  while (currDom) {
    if (prevDom) {
      const element = currDom.cloneNode(false)
      element.appendChild(prevDom)
      prevDom = element
    } else {
      prevDom = currDom.cloneNode(true)
    }
    currDom = currDom.parentElement
  }
  return prevDom
}
const getStyle = (options) => {
  let str = ''
  const styles = document.querySelectorAll('style,link')
  for (let i = 0; i < styles.length; i++) {
    str += styles[i].outerHTML
  }
  str +=
    '<style>' +
    (options.noPrint ? options.noPrint : '.no-print') +
    '{display:none;}</style>'
  return str
}
const getHtml = (dom, options) => {
  const inputs = document.querySelectorAll('input')
  const textAreas = document.querySelectorAll('textarea')
  const selects = document.querySelectorAll('select')

  for (let k = 0; k < inputs.length; k++) {
    if (inputs[k].type === 'checkbox' || inputs[k].type === 'radio') {
      if (inputs[k].checked === true) {
        inputs[k].setAttribute('checked', 'checked')
      } else {
        inputs[k].removeAttribute('checked')
      }
    } else if (inputs[k].type === 'text') {
      inputs[k].setAttribute('value', inputs[k].value)
    } else {
      inputs[k].setAttribute('value', inputs[k].value)
    }
  }

  for (let k2 = 0; k2 < textAreas.length; k2++) {
    if (textAreas[k2].type === 'textarea') {
      textAreas[k2].innerHTML = textAreas[k2].value
    }
  }

  for (let k3 = 0; k3 < selects.length; k3++) {
    if (selects[k3].type === 'select-one') {
      const child = selects[k3].children
      for (const i in child) {
        if (child[i].tagName === 'OPTION') {
          if (child[i].selected === true) {
            child[i].setAttribute('selected', 'selected')
          } else {
            child[i].removeAttribute('selected')
          }
        }
      }
    }
  }
  return options.noPrintParent ? dom.outerHTML : wrapperRefDom(dom).outerHTML
}
const toPrint = (frameWindow) => {
  try {
    setTimeout(function () {
      frameWindow.focus()
      try {
        if (!frameWindow.document.execCommand('print', false, null)) {
          frameWindow.print()
        }
      } catch (e) {
        frameWindow.print()
      }
      frameWindow.close()
    }, 10)
  } catch (err) {
    console.log('err', err)
  }
}
const writeIframe = (content) => {
  const iframe = document.createElement('iframe')
  const f = document.body.appendChild(iframe)
  iframe.id = 'myIframe'
  iframe.setAttribute(
    'style',
    'position:absolute;width:0;height:0;top:-10px;left:-10px;'
  )
  const w = f.contentWindow || f.contentDocument
  const doc = f.contentDocument || f.contentWindow.document
  doc.open()
  doc.write(content)
  doc.close()
  iframe.onload = function () {
    toPrint(w)
    setTimeout(function () {
      document.body.removeChild(iframe)
    }, 100)
  }
}

const Print = (dom, options) => {
  options = { ...options, noPrint: '.no-print' }
  let targetDom
  if (typeof dom === 'string') {
    targetDom = document.querySelector(dom)
  } else {
    targetDom = isDOM(dom) ? dom : dom.$el
  }

  const content = getStyle(options) + getHtml(targetDom, options)
  writeIframe(content)
}

export default Print
