import React, {Fragment} from "react"
import "focus-visible"
import {Provider} from "react-redux"
import {ParallaxProvider} from 'react-scroll-parallax'
import {BrowserRouter, Route} from "react-router-dom"
import {createStore, combineReducers} from "redux"
import DecoratedPreview from "./preview"
import "./style.css"
import {CHANGE_UIKIT} from "./actions"
import _ from "lodash/fp"
import sandboxData from "weblium/sandbox-data.json"
import $editor from "weblium/editor"
import {api} from '../../editor/api'


export const fetchUikit = async (uikitId) => {
  const ukitPath = `https://cdn.rawgit.com/webliumteam/blocks/${sandboxData.uikitsList[uikitId]}/`
  const [uikitPalette, uikitTypography, uikitButton] = await Promise.all([
    fetch(`${ukitPath}src/palette.json`).then((response) => response.json()),
    fetch(`${ukitPath}src/typography.json`).then((response) => response.json()),
    fetch(`${ukitPath}src/buttons.json`).then((response) => response.json()),
  ])
  return {uikitPalette, uikitTypography, uikitButton}
}

const getReducer = () => {
  const resources = (state = {}, action) => {
    switch (action.type) {
    case `FETCH_RESOURCE`: {
      const {resourceRef} = action.payload
      const resource = _.find(({ref}) => ref === resourceRef)(window.stubImages) || {}
      const width = _.get('props.size.width')(resource)
      const height = _.get('props.size.height')(resource)
      return {...state, [resourceRef]: {optimized: resourceRef, ...resource, width, height}}
    }
    default: {
      return state
    }
    }
  }
  const uiKit = (state = {}, action) => {
    switch (action.type) {
    case CHANGE_UIKIT: {
      const {id, data} = action
      const uiKit = $editor.uiKit.generateUIKit(data)
      return {id, ...uiKit}
    }
    default: {
      return state
    }
    }
  }
  const pages = (state = {}, action) => state
  const blocks = (state = {}, action) => {
    switch (action.type) {
    case 'UPDATE_BLOCK':
    case 'FETCH_BLOCK_FULFILLED': {
      const {id, block} = action.payload
      return {...state, [id]: block}
    }
    default: {
      return state
    }
    }
  }
  const rootReducer = combineReducers({
    website: (state = {}) => state,
    ...($editor.reducers ? $editor.reducers : {blocks}),
    resources,
    uiKit,
    pages,
    loading: (state = [], action) => state,
    distorted: (state = false, action) => {
      if (action.type === 'TOGGLE_DISTORT') {
        return action.value
      }
      return state
    },
  })
  return rootReducer
}

const getStore = async () => {
  const {blockUikitId} = sandboxData
  const initialState = {}

  if (__MODE__ === 'theme-version') {
    const themeBlocks = require('weblium/theme-blocks')
    try {
      const {data} = await api.block.list({query: {filter: {wireframe: true}}})
      Object.assign(initialState, {blocks: {}})
      for (const i in themeBlocks) {
        const themeBlock = themeBlocks[i]
        const wireframeBlock = _.find(({name}) => name === themeBlock)(data) || {}
        if (wireframeBlock) {
          const {_id: blockId, ...block} = wireframeBlock
          Object.assign(initialState.blocks, {[blockId]: {id: blockId, ...block, modifier: JSON.stringify({__enableThemes: true})}})
        }
      }
    } catch (e) {}
  }
  const uikitdata = await fetchUikit(blockUikitId)
  const resources = {}
  const uiKit = {id: blockUikitId, ...$editor.uiKit.generateUIKit(uikitdata)}
  const pages = {
    page: {metadata: {homepage: true}, ready: true},
  }

  Object.assign(initialState, {
    resources,
    uiKit,
    pages,
    website: {...uikitdata, _id: 'myfancywebsite'},
  })

  const middleware = $editor.storeMiddleware
    ? $editor.storeMiddleware
    : global.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || _.noop
  const rootReducer = getReducer()
  const store = createStore(rootReducer, initialState, middleware())
  global.setStore && global.setStore(store)
  $editor.uiKit.loadFontsFromUiKit(uiKit)
  return {store, ModalsManager: $editor.ModalsManager}
}

class App extends React.Component {
  state = {
    loading: true,
  }

  async componentWillMount() {
    $editor.takeOverConsole && $editor.takeOverConsole()
    const {store, ModalsManager} = await getStore()
    
    this.store = store
    this.ModalsManager = ModalsManager
    if (__MODE__ === 'theme-version') {
      const {blocks} = store.getState()
      for (const blockId in blocks) {
        const {viewRef} = blocks[blockId]
        store.dispatch(await $editor.getAndSetView({viewRef}))
      }
    }
    this.setState({loading: false})
  }

  render() {
    const {loading} = this.state
    return loading ? null : (
      <ParallaxProvider>
        <Provider store={this.store}>
          <Fragment>
            <BrowserRouter location="/" context={{}}>
              <Route path="*" render={() => <DecoratedPreview />} />
            </BrowserRouter>
            {this.ModalsManager && <this.ModalsManager />}
          </Fragment>
        </Provider>
      </ParallaxProvider>
    )
  }
}

export default App
