import * as AccUtils from "../accUtils";
import * as ko from "knockout";
import MutableArrayDataProvider = require("ojs/ojmutablearraydataprovider");
import "ojs/ojselectsingle";
import "ojs/ojlabel";
import "ojs/ojchart";
import * as storeData from "text!../store_data.json";
import "ojs/ojlistview";
import "ojs/ojavatar";
import { ObservableKeySet } from "ojs/ojknockout-keyset";
import { ojListView } from "ojs/ojlistview";

type ChartType = {
  value: string;
  label: string;
};

type Activity = {
  id: number;
};

type Item = {
  id: number;
  name: string;
  short_desc: string;
  price: number;
  quantity: number;
  quantity_shipped: number;
  quantity_instock: number;
  activity_id: number;
  image: string;
};

type ActivityItems = {
  id: number;
  name: string;
  items: Array<Item>;
  short_desc: string;
  image: string;
};

class DashboardViewModel {
  activityDataProvider: MutableArrayDataProvider<Activity["id"], Activity>;
  itemsArray: Array<Object>;
  itemsDataProvider: MutableArrayDataProvider<Item["id"], Item>;
  itemData: ko.Observable<any>;
  pieSeriesValue: ko.ObservableArray;
  // Observables for Activities
  selectedActivity = new ObservableKeySet();
  activitySelected = ko.observable(false);  // Controls display of Activity Items
  firstSelectedActivity = ko.observable();
  selectedActivityIds = ko.observable();

  // Observables for Activity Items
  itemSelected = ko.observable(false);
  selectedItem = ko.observable();
  firstSelectedItem = ko.observable();

  constructor() {
    this.activityDataProvider = new MutableArrayDataProvider<
      Activity["id"],
      Activity
    >(JSON.parse(storeData), {
      keyAttributes: "id",
    });

    let activitiesArray = JSON.parse(storeData);
    let itemsArray = activitiesArray[0].items;

    this.itemsDataProvider = new MutableArrayDataProvider<Item["id"], Item>(
      itemsArray,
      { keyAttributes: "id" }
    );

    this.itemData = ko.observable('');
    this.itemData(activitiesArray[0].items[0]);

    this.pieSeriesValue = ko.observableArray([]);

    let pieSeries = [
      { name: "Quantity in Stock", items: [this.itemData().quantity_instock] },
      { name: "Quantity Shipped", items: [this.itemData().quantity_shipped] }
    ];
    this.pieSeriesValue(pieSeries);
  }

  selectedActivityChanged = (event: ojListView.firstSelectedItemChanged<ActivityItems["id"], ActivityItems>) => {
    /**
    *  If no items are selected then the firstSelectedItem property  returns an object 
    *  with both key and data properties set to null.
    */
    let itemContext = event.detail.value.data;

    if (itemContext != null) {
      // If selection, populate and display list
      // Hide currently-selected activity item
      this.activitySelected(false);

      let itemsArray = itemContext.items;
      this.itemsDataProvider.data = itemsArray;
      // Set List View properties
      this.activitySelected(true);
      this.itemSelected(false);
      this.selectedItem();
      this.itemData();

    } else {
      // If deselection, hide list         
      this.activitySelected(false);
      this.itemSelected(false);
    }
  };

  /**
   * Handle selection from Activity Items list
   */
  selectedItemChanged = (event: ojListView.firstSelectedItemChanged<Item["id"], Item>) => {

    let isClicked = event.detail.value.data;

    if (isClicked != null) {

      // If selection, populate and display list
      this.itemData(event.detail.value.data);

      // Create variable and get attributes of the items list to set pie chart values
      let pieSeries = [
        { name: "Quantity in Stock", items: [this.itemData().quantity_instock] },
        { name: "Quantity Shipped", items: [this.itemData().quantity_shipped] }
      ];
      // Update the pie chart with the data
      this.pieSeriesValue(pieSeries);

      this.itemSelected(true);

    }
    else {
      // If deselection, hide list
      this.itemSelected(false);
    }
  };

  /**
   * Optional ViewModel method invoked after the View is inserted into the
   * document DOM.  The application can put logic that requires the DOM being
   * attached here.
   * This method might be called multiple times - after the View is created
   * and inserted into the DOM and after the View is reconnected
   * after being disconnected.
   */
  connected(): void {
    AccUtils.announce("Dashboard page loaded.");
    document.title = "Dashboard";
    // implement further logic if needed
  }

  /**
   * Optional ViewModel method invoked after the View is disconnected from the DOM.
   */
  disconnected(): void {
    // implement if needed
  }

  /**
   * Optional ViewModel method invoked after transition to the new View is complete.
   * That includes any possible animation between the old and the new View.
   */
  transitionCompleted(): void {
    // implement if needed
  }
}

export = DashboardViewModel;
