<!DOCTYPE html>
<html>
<head>
  <link data-require="bootstrap@*" data-semver="4.0.5" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" />
<script data-require="rxjs@*" data-semver="5.1.1" src="https://unpkg.com/rxjs@5.1.1/bundles/Rx.min.js"></script>
  <script data-require="redux@*" data-semver="3.2.1" src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.2.1/redux.js"></script>
  <script data-require="jquery@*" data-semver="3.1.1" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
  <script data-require="bootstrap@*" data-semver="4.0.5" src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js"></script>
</head>

<body>
  <div class="container">
    <div id="productsContainer">
      <fieldset>
        <h2>Products</h2>
        <div>
          <label>Product Type: </label>
          <select class="select">
            <option value="1">
              Cosmetic
            </option>
             <option value="2">
              Grocery
            </option>
               <option value="3">
              Fashion
            </option>
          </select>
          Product Name:
          <input id="productName" />
          <button id="btnAdd" class="btn btn-success">Add</button>
        </div>
        <button id="btnSaveToServer" class="btn btn-info">Save to Server</button>
      </fieldset>
      <br>
      <div class="list-group" id="productList">

      </div>
    </div>
  </div>
  <script src="rx-store.js"></script>
  <script src="products/state.js"></script>
  <script src="products/actions.js"></script>
  <script src="products/reducer.js"></script>
  <script src="products/index.js"></script>
  <script src="products/product-selectors.js"></script>
  <script src="products/product-controller.js"></script>
  <script src="products/product-container-controller.js"></script>
</body>

</html>
/* Styles go here */

function productApp(state = initialState, action = {}) {
  switch (action.type) {
    case 'ADD':
      {
        return Object.assign({},state, {
          items: [...state.items, action.payload]
        });
      }
      case 'DELETE':
      {
        return Object.assign({},state, {
          items: state.items.filter(i=>i.id!==action.payload.id)
        });
      }
      case 'UPDATE_PRICE':
        {
          return Object.assign({},state,{items:
            state.items.map(i=>{
              if(i.id===action.payload.id) {
                return {...i, price: action.payload.price};
              }
              return i;
            })
          });
        }
    case 'VOTE':
      {
        return Object.assign({},state, {
          ratings: state.ratings.map(function(r) {
            if (r.star === action.payload.star) {
              return Object.assign({},r, {
                votes: r.votes + 1
              });

            }
            return r;
          })
        });
      }
    default:
      return state;
  }
}
var {
  combineReducers
} = Redux;

var reducer = combineReducers({
  products: productApp
});

store$.provideStore(reducer);
var productsController = (function(
  store$, getRatings, getItems, addAction, voteAction, updatePriceAction, getProducts, productController
) {
  var products$ = store$.select(getProducts);
  var ratings$ = store$.select(getRatings);
  var items$ = store$.select(getItems);
  var addClick$ = Rx.Observable.fromEvent(document.getElementById('btnAdd'), 'click');
  var saveToServer$ = Rx.Observable.fromEvent(document.getElementById('btnSaveToServer'), 'click');

  addClick$.subscribe(addProduct);
  saveToServer$.withLatestFrom(products$).map(v => v[1]).subscribe(saveToServer);

  ratings$.subscribe(onRatingsChange);
  items$.subscribe(onItemsChange);


  return {
    onPriceChange: onPriceChange,
    onDelete: onDelete
  };

  function onDelete(id) {
    store$.dispatch(deleteAction(id));
  }

  function onPriceChange(id, price) {
    store$.dispatch(updatePriceAction(id, price));
  }

  function onRatingsChange(ratings) {
    console.log('new ratings', ratings);
  }

  function onItemsChange(items) {
    console.log('new items', items);

    var $products = $('#productList').empty();

    items.forEach((item) => {
      $products.append(productController.render({
        item,onDelete,onPriceChange
      }));
    });
  }

  function addProduct() {
    var $name = $('#productName');
    store$.dispatch(addAction(uniqueKey(), $name.val()));
    $name.val('');
  }

  function saveToServer(allProducts) {
    debugger;
    // publish event to save server
  }

  function uniqueKey() {
    return '_' + Math.random().toString(36).substr(2, 9);
    // https://gist.github.com/gordonbrander/2230317
  }

  function vote(star) {
    store$.dispatch(voteAction(star));
  }

})(store$, getRatings, getItems, addAction, voteAction, updatePriceAction, getProducts,productController);
var store$ = (function(createStore) {
  var store;
  var state;
  var _state;
  var state$;

  return {
    dispatch: dispatch,
    select: select,
    provideStore: provideStore
  };

  function dispatch(action) {
    store.dispatch(action);
  }

  function select(selectorFunction) {
    return state$.map(selectorFunction).distinctUntilChanged();
  }

  function provideStore(reducers, initialState) {
    store = createStore(reducers);
    state = initialState | {};
    state = store.getState();
    _state = new Rx.BehaviorSubject(state);
    state$ = _state.asObservable().distinctUntilChanged();
    store.subscribe(function() {
      _state.next(store.getState());
    });
  }
})(Redux.createStore);
;

function getProducts(state) {
  return state.products;
}

function getRatings(state) {
  return getProducts(state).ratings;
}

function getItems(state) {
  return getProducts(state).items;
}
var addAction = function(id, name) {
  return {
    type: 'ADD',
    payload: {
      id: id,
      name: name
    }
  };
};

var voteAction = (star) => ({
  type: 'VOTE',
  payload: {
    star
  }
});

var updatePriceAction = (id, price) => ({
  type: 'UPDATE_PRICE',
  payload: {
    price, id
  }
});

var deleteAction = (id) => ({
  type: 'DELETE',
  payload: {
    id
  }
});
var initialState = {
  items: [{
    id: '1',
    name: 'computer',
    price: '30'
  }],
  ratings: [{
    star: 1,
    votes: 0
  }, {
    star: 2,
    votes: 0
  }, {
    star: 3,
    votes: 0
  }, {
    star: 4,
    votes: 0
  }, {
    star: 5,
    votes: 0
  }]
};
var productEffects = (function(){
  
})(store$);
var productController = (function() {
  var props;
  return {
    render: render
  };

  function render(props) {
    props = props;
    return $(`
        <div class="list-group-item">
            <div class="col-md-6">
                ${props.item.name}
            </div>
            <div class="col-md-6">
                <label>Price in $: </label> 
                <input class="productPrice" 
                       value=${props.item.price||0} />
                       <button class="btn btn-danger product-delete">
                       Delete
                       </button>  </div>
             
         </div>
      `)
      .on('click', function(e) {
        handleClick(props, e);
      })
      .change(function(e) {
        handlePriceChange(props, e);
      });
  }

  function handleClick(props, e) {
    var $target = $(e.target);
    if ($target.hasClass('product-delete')) {
      handleItemDelete(props);
    }
    e.preventDefault();
  }
  
  function handleItemDelete(props) {
    props.onDelete(props.item.id);
  }

  function handlePriceChange(props, e) {
    var $target = $(e.target);
    props.onPriceChange(props.item.id, $target.val());
    e.preventDefault();
  }
})();