import {ReferenceInput} from '../../index'

import {materializeReferences, referenceSearch, fetch} from '../data/fetch'
import {once} from 'lodash'
import {observeForPreview, resolveRefType} from 'part:@sanity/base/preview'


const ReferenceBrowser = ReferenceInput.createBrowser({
  fetch,
  materializeReferences
})

export function materializeReference(id) {
  return materializeReferences([id]).then(res => res[0])
}

function observableToPromise(observable) {
  return new Promise((resolve, reject) => {
    const subscription = observable.subscribe({
      next: val => {
        subscription.unsubscribe()
        resolve(val)
      },
      error: reject
    })
  })
}
function valueToString(value, type) {
  return resolveRefType(value, type)
    .then(refType => observableToPromise(observeForPreview(value, refType)))
    .then(res => res.title)
}

const ReferenceSearchableSelect = ReferenceInput.createSearchableSelect({
  search: referenceSearch,
  valueToString: valueToString
})

const ReferenceSelect = ReferenceInput.createSelect({
  fetchAll: fetch,
  materializeReferences
})

// eslint-disable-next-line no-console
const warnNoSearchYet = once(() => console.warn('Reference browser does not yet support search'))

export default function resolveReference(type) {
  const options = type.options || {}
  if (options.inputType === 'select') {
    return options.searchable
      ? ReferenceSearchableSelect
      : ReferenceSelect
  }

  if (options.inputType === 'browser') {
    if (options.searchable) {
      warnNoSearchYet()
    }
    return ReferenceBrowser
  }

  return ReferenceSearchableSelect
}

import {ReferenceInput} from '../../index'

import {materializeReferences, referenceSearch, fetch} from '../data/fetch'
import {once} from 'lodash'
import {observeForPreview, resolveRefType} from 'part:@sanity/base/preview'


const ReferenceBrowser = ReferenceInput.createBrowser({
  fetch,
  materializeReferences
})

export function materializeReference(id) {
  return materializeReferences([id]).then(res => res[0])
}

function observableToPromise(observable) {
  let subscription
  return new Promise((resolve, reject) => {
    subscription = observable.subscribe({
      next: val => {
        resolve(val)
      },
      error: reject
    })
  }).then(result => {
    subscription.unsubscribe()
    return result
  })
}
function valueToString(value, type) {
  return resolveRefType(value, type)
    .then(refType => observableToPromise(observeForPreview(value, refType)))
    .then(res => res.title)
}

const ReferenceSearchableSelect = ReferenceInput.createSearchableSelect({
  search: referenceSearch,
  valueToString: valueToString
})

const ReferenceSelect = ReferenceInput.createSelect({
  fetchAll: fetch,
  materializeReferences
})

// eslint-disable-next-line no-console
const warnNoSearchYet = once(() => console.warn('Reference browser does not yet support search'))

export default function resolveReference(type) {
  const options = type.options || {}
  if (options.inputType === 'select') {
    return options.searchable
      ? ReferenceSearchableSelect
      : ReferenceSelect
  }

  if (options.inputType === 'browser') {
    if (options.searchable) {
      warnNoSearchYet()
    }
    return ReferenceBrowser
  }

  return ReferenceSearchableSelect
}

Add a hacky way of unsubscribing until Reference inputs supports observables