import React, { Component } from 'react';
import { createAction } from 'dispersive/action';
import { createModel } from 'dispersive/model';
import { withField } from 'dispersive/field';
import { withOne, withMany } from 'dispersive/relation';
import { Watcher } from 'react-dispersive';
import request from 'request-promise-json';

const MAX_NUM = 151;  // limiting to first generation
const POKEMON_URL = 'http://pokeapi.co/api/v2/pokemon';


/*
 * Models
 */

const Pokemon = createModel([
  withField('name'),
  withField('sprite'),
]);

const PokedexSlot = createModel([
  withField('num'),
  withField('active'),
  withField('loading', { initial: false }),
  withField('seen', { initial: false }),
  withField('captured', { initial: false }),
  withOne('pokemon', Pokemon),
]);

const Pokedex = createModel([
  withMany('slots', {model: PokedexSlot, relatedName: 'pokedex'}),
]);

/*
 * Actions
 */

const createPokedex = createAction(({limit}) => {
  const pokedex = Pokedex.objects.create();

  for (const num = 1; num <= limit; ++num) {
    pokedex.slots.add(PokedexSlot.objects.create({ num }))
  }

  return pokedex;
}, [Pokedex, PokedexSlot]);

const setActiveSlot = createAction((slot) => {
  slot.pokedex.slots.filter({active: true}).update({update: false});
  slot.update({active: true});
}, [PokedexSlot]);

const setSlotDownloading = createAction((slot, downloading) => slot.update({downloading}), [PokedexSlot]);

const addPokemonOnSlot = createAction(async (slot) => {
  const data = await request(`${POKEMON_URL}/${slot.num}`);

  slot.pokemon = Pokemon.objects.create(data);
}, [Pokemon, PokedexSlot])

const setSlotVisible = async (slot) => {
  if (!slot.pokemon) {
    await setSlotDownloading(slot, true);
    await addPokemonOnSlot(slot);
    await setSlotDownloading(slot, false);
  }
}

/*
 * Components
 */

class PokedexListSlot extends Component {

  shouldComponentUpdate({slot}) {
    return !this.props.slot.equals(slot);
  }

  render() {
    console.log('render', Date.now())
    const {slot} = this.props;

    return (
      <li onMouseDown={() => {console.log('click', Date.now());setActiveSlot(slot)} }>
        {`#${slot.num}`}
        <span>{slot.active ? 'active' : null}</span>
      </li>
    );
  }
}

const PokedexList = ({pokedex}) => {

  return (
  <ul>
  {pokedex ? pokedex.slots.orderBy('num').map(slot => (
    <PokedexListSlot slot={slot} key={slot.pk} />)
  ) : null}
  </ul>
)};

const PokedexApp = () => (
  <div className="pokedex-app">
    <PokedexList pokedex={Pokedex.objects.get()} />
  </div>
);

class App extends Component {

  componentDidMount() {
    createPokedex({limit: MAX_NUM});
  }

  render() {
    return (
      <Watcher sources={[Pokemon, Pokedex, PokedexSlot]}>
        <PokedexApp />
      </Watcher>
    );
  }
}

export default App;

@@ -608,16 +608,36 @@
 'active'
+, %7B initial: false %7D
 ),%0A  wit
@@ -1268,21 +1268,21 @@
 update(%7B
-updat
+activ
 e: false
@@ -1894,270 +1894,150 @@
 t %7B%0A
-%0A
   s
-houldComponentUpdate(%7Bslot%7D) %7B%0A    return !this.props.slot.equals(slot);%0A  %7D%0A%0A  render() %7B%0A    console.log('render', Date.now())%0A    const %7Bslot%7D = this.props;%0A%0A    return (%0A      %3Cli onMouseDown=%7B() =%3E %7Bconsole.log('click', Date.now());setActiveSlot(slot)%7D 
+etActive = () =%3E setActiveSlot(this.props.slot)%0A%0A  render() %7B%0A    console.log('render');%0A    return (%0A      %3Cli onMouseDown=%7Bthis.setActive
 %7D%3E%0A 
@@ -2048,16 +2048,27 @@
    %7B%60#$%7B
+this.props.
 slot.num
@@ -2084,50 +2084,64 @@
    %3C
-span%3E%7Bslot.active ? 'active' : null%7D%3C/span
+input type=%22checkbox%22 checked=%7Bthis.props.slot.active%7D /
 %3E%0A  
@@ -2202,20 +2202,8 @@
 ) =%3E
- %7B%0A%0A  return
  (%0A 
@@ -2336,17 +2336,16 @@
  %3C/ul%3E%0A)
-%7D
 ;%0A%0Aconst

fix setActiveSlot