// Root application: hash-based routing + cart/checkout state.
(function () {
  var useState = React.useState;
  var useEffect = React.useEffect;

  function getRoute() {
    return window.location.hash || '#/';
  }

  function App() {
    var routeState = useState(getRoute());
    var route = routeState[0];
    var setRoute = routeState[1];
    var cartState = useState([]); // [{ product, quantity }]
    var cart = cartState[0];
    var setCart = cartState[1];
    var orderState = useState(null);
    var lastOrder = orderState[0];
    var setLastOrder = orderState[1];

    useEffect(function () {
      function onHashChange() {
        setRoute(getRoute());
        window.scrollTo(0, 0);
      }
      window.addEventListener('hashchange', onHashChange);
      return function () { window.removeEventListener('hashchange', onHashChange); };
    }, []);

    function navigate(path) {
      window.location.hash = path;
    }

    function addToCart(product, quantity) {
      setCart(function (prev) {
        var existing = prev.filter(function (e) { return e.product.id === product.id; })[0];
        if (existing) {
          return prev.map(function (e) {
            return e.product.id === product.id ? { product: product, quantity: e.quantity + quantity } : e;
          });
        }
        return prev.concat([{ product: product, quantity: quantity }]);
      });
    }

    function incrementCartItem(product) {
      window.GTMEvents.addToCart(product, 1);
      addToCart(product, 1);
    }

    function decrementCartItem(product) {
      var entry = cart.filter(function (e) { return e.product.id === product.id; })[0];
      if (!entry) {
        return;
      }
      window.GTMEvents.removeFromCart(product, 1);
      setCart(function (prev) {
        return prev
          .map(function (e) {
            return e.product.id === product.id ? { product: e.product, quantity: e.quantity - 1 } : e;
          })
          .filter(function (e) { return e.quantity > 0; });
      });
    }

    function removeCartItem(product) {
      var entry = cart.filter(function (e) { return e.product.id === product.id; })[0];
      if (!entry) {
        return;
      }
      window.GTMEvents.removeFromCart(product, entry.quantity);
      setCart(function (prev) { return prev.filter(function (e) { return e.product.id !== product.id; }); });
    }

    function beginCheckout() {
      window.GTMEvents.beginCheckout(cart);
      navigate('#/checkout');
    }

    function addShippingInfo(shippingTier) {
      window.GTMEvents.addShippingInfo(cart, shippingTier);
    }

    function addPaymentInfo(paymentType) {
      window.GTMEvents.addPaymentInfo(cart, paymentType);
    }

    function placeOrder(shippingCost, tax) {
      var transactionId = 'T' + Date.now();
      window.GTMEvents.purchase(cart, transactionId, shippingCost, tax);
      var subtotal = cart.reduce(function (sum, e) { return sum + e.product.price * e.quantity; }, 0);
      setLastOrder({
        transactionId: transactionId,
        cart: cart,
        total: subtotal + shippingCost + tax
      });
      setCart([]);
      navigate('#/confirmation');
    }

    var cartCount = cart.reduce(function (sum, e) { return sum + e.quantity; }, 0);

    var page;
    if (route.indexOf('#/product/') === 0) {
      var productId = route.replace('#/product/', '');
      page = React.createElement(window.ProductDetail, {
        productId: productId,
        products: window.PRODUCTS,
        navigate: navigate,
        onAddToCart: addToCart
      });
    } else if (route === '#/cart') {
      page = React.createElement(window.Cart, {
        cart: cart,
        navigate: navigate,
        onIncrement: incrementCartItem,
        onDecrement: decrementCartItem,
        onRemove: removeCartItem,
        onBeginCheckout: beginCheckout
      });
    } else if (route === '#/checkout') {
      page = React.createElement(window.Checkout, {
        cart: cart,
        navigate: navigate,
        onAddShippingInfo: addShippingInfo,
        onAddPaymentInfo: addPaymentInfo,
        onPlaceOrder: placeOrder
      });
    } else if (route === '#/confirmation') {
      page = React.createElement(window.Confirmation, { order: lastOrder, navigate: navigate });
    } else {
      page = React.createElement(window.ProductList, {
        products: window.PRODUCTS,
        navigate: navigate
      });
    }

    return (
      <div className="app">
        <window.Header cartCount={cartCount} navigate={navigate} />
        <main className="main-content">{page}</main>
        <window.DataLayerPanel />
      </div>
    );
  }

  window.App = App;
})();
