import {
  PHX_VIEW_SELECTOR
} from "./constants"

import EntryUploader from "./entry_uploader"

export let logError = (msg, obj) => console.error && console.error(msg, obj)

export let isCid = (cid) => {
  let type = typeof(cid)
  return type === "number" || (type === "string" && /^(0|[1-9]\d*)$/.test(cid))
}

export function detectDuplicateIds(){
  let ids = new Set()
  let elems = document.querySelectorAll("*[id]")
  for(let i = 0, len = elems.length; i < len; i++){
    if(ids.has(elems[i].id)){
      console.error(`Multiple IDs detected: ${elems[i].id}. Ensure unique element ids.`)
    } else {
      ids.add(elems[i].id)
    }
  }
}

export function detectInvalidStreamInserts(inserts){
  const errors = new Set()
  Object.keys(inserts).forEach((id) => {
    const streamEl = document.getElementById(id)
    if(streamEl && streamEl.parentElement && streamEl.parentElement.getAttribute("phx-update") !== "stream"){
      errors.add(`The stream container with id "${streamEl.parentElement.id}" is missing the phx-update="stream" attribute. Ensure it is set for streams to work properly.`)
    }
  })
  errors.forEach(error => console.error(error))
}

export let debug = (view, kind, msg, obj) => {
  if(view.liveSocket.isDebugEnabled()){
    console.log(`${view.id} ${kind}: ${msg} - `, obj)
  }
}

// wraps value in closure or returns closure
export let closure = (val) => typeof val === "function" ? val : function (){ return val }

export let clone = (obj) => { return JSON.parse(JSON.stringify(obj)) }

export let closestPhxBinding = (el, binding, borderEl) => {
  do {
    if(el.matches(`[${binding}]`) && !el.disabled){ return el }
    el = el.parentElement || el.parentNode
  } while(el !== null && el.nodeType === 1 && !((borderEl && borderEl.isSameNode(el)) || el.matches(PHX_VIEW_SELECTOR)))
  return null
}

export let isObject = (obj) => {
  return obj !== null && typeof obj === "object" && !(obj instanceof Array)
}

export let isEqualObj = (obj1, obj2) => JSON.stringify(obj1) === JSON.stringify(obj2)

export let isEmpty = (obj) => {
  for(let x in obj){ return false }
  return true
}

export let maybe = (el, callback) => el && callback(el)

export let channelUploader = function (entries, onError, resp, liveSocket){
  entries.forEach(entry => {
    let entryUploader = new EntryUploader(entry, resp.config, liveSocket)
    entryUploader.upload()
  })
}
