<reponame>samuelili/canvas-plus<gh_stars>1-10
let DEFAULT_INSTANCE = {
  courses: {},
  courseIds: [],
  hiddenCourseIds: [],
  settings: {
    tabsEnabled: true,
    gradesEnabled: true,
    upcomingAssignmentsEnabled: true,
    gradeTagsEnabled: true
  }
}

// we maintain local state here
// also default settings
let state = {
};

// resetting legacy settings goes here in case of version differences
function resetLegacy() {

}

// resetting legacy settings for each instance goes here
function resetLegacyInstance(instance) {
  if (Array.isArray(state[instance].courses)) {
    state[instance].courses = {};
  }
}

chrome.storage.sync.get({
  instances: [],
}, items => {
  state.instances = items.instances;
  for (let instance of items.instances) {
    let request = {};
    request[instance] = DEFAULT_INSTANCE;
    chrome.storage.sync.get(request, items => {
      if (items[instance]) {
        state[instance] = {...DEFAULT_INSTANCE, ...items[instance]};
      }
      resetLegacyInstance(instance)
    });
  }

  console.log(state);
  resetLegacy();
});


function sync(instance) {
  let request = {};
  request[instance] = state[instance];
  chrome.storage.sync.set(request, () => console.log('Updated sync', instance, state[instance]))
}

// get everything
function get(request, sender, sendResponse) {
  sendResponse(state);
}

// set everything
function set(request, sender, sendResponse) {
  state = request.state;
  console.log('Updated with state', request.state);
  chrome.storage.sync.set(state, () => console.log('Updated entire state'));
  sendResponse(true);
}

// register an instance
function registerInstance(request, sender, sendResponse) {
  if (!Object.keys(state).includes(request.instance)) {
    state.instances.push(request.instance);
    state[request.instance] = DEFAULT_INSTANCE;
  } else {
    state[request.instance] = {...DEFAULT_INSTANCE, ...state[request.instance]};
  }

  console.log("Sending", state[request.instance]);
  sync(request.instance);
  sendResponse(state[request.instance]);
  // if (!state.instances.includes(request.instance) || Object.keys(state[request.instance]).length === 0) {
  //   if (!state.instances.includes(request.instance))
  //     state.instances.push(request.instance);
  //   state[request.instance] = DEFAULT_INSTANCE;
  //   chrome.storage.sync.set({instances: state.instances}, () => console.log('Updated sync instances', state.instances));
  // } else {
  //   console.log(request.instance, 'already registered!');
  // }
}

// update courses
function setCourses(request, sender, sendResponse) {
  let instance = state[request.instance];
  let newCourses = request.courses;

  for (let course of newCourses) {
    instance.courses[course.id] = {
      name: course.name,
      custom: "",
      id: course.id,
      ...(instance.courses[course.id] || {}) // if it doesn't exist, just use an empty object
    };

    if (!instance.courseIds.includes(course.id) && !instance.hiddenCourseIds.includes(course.id)) {
      instance.courseIds.push(course.id);
    }
  }

  sync(instance);
  sendResponse(instance);
}

// get courses
function getCourses({instance}, sender, sendResponse) {
  let returnObj = {};
  for (let course of state[instance].courses) {
    returnObj[course] = state[instance][course]
  }
  sendResponse(returnObj);
}

// set settings
function setSetting({instance, key, value}, sender, sendResponse) {
  state[instance].settings[key] = value;
  sync(instance);
}

// get settings
function getSetting({instance, key}, sender, sendResponse) {
  sendResponse(state[instance].settings[key]);
}

// set settings
function getTabs({instance}, sender, sendResponse) {
  let courses = [];
  state[instance].courses.forEach(courseId =>
      courses.push({
        ...state[instance][courseId],
        id: courseId
      }));
  sendResponse({
    courses: courses,
    enabled: state[instance].settings.tabsEnabled
  })
}

function reset() {
  state = {

  }
}

//example of using a message handler from the inject scripts
chrome.extension.onMessage.addListener(
  function (request, sender, sendResponse) {
    console.log('got action', request.action);
    switch (request.action) {
      case "GET":
        get(request, sender, sendResponse);
        break;
      case "SET":
        set(request, sender, sendResponse);
        break;
      case "REGISTER_INSTANCE":
        registerInstance(request, sender, sendResponse);
        break;
      case "SET_COURSES":
        setCourses(request, sender, sendResponse);
        break;
      case "GET_COURSES":
        getCourses(request, sender, sendResponse);
        break;
      case "SET_SETTING":
        setSetting(request, sender, sendResponse);
        break;
      case "GET_SETTING":
        getSetting(request, sender, sendResponse);
        break;
      case "GET_TABS":
        getTabs(request, sender, sendResponse);
        break;
      case "OPTIONS":
        if (chrome.runtime.openOptionsPage) {
          chrome.runtime.openOptionsPage();
        } else {
          chrome.tabs.create({
            url: chrome.runtime.getURL('src/options/options.html')
          })
        }
        break;
    }
  });