import {Map} from 'immutable';

import LC3 from './core/lc3';
import LC3Program from './core/program';
import * as Constants from './core/constants';

const initialState = Map({
    lc3: new LC3(),
    viewOptions: Map({
        topAddressShown: 0x3000,
        followPC: true,
    }),
});

function setPC(state, newPC) {
    return state.setIn(["lc3", "registers", "pc"], newPC);
}

function setMemory(state, address, value) {
    return state.setIn(["lc3", "memory", address], value);
}

function setRegister(state, name, value) {
    return state.setIn(["lc3", "registers", name], value);
}

function loadProgram(state, program) {
    const data = new LC3Program.fromJS(program);
    return state.update("lc3", lc3 => lc3.loadProgram(data));
}

function scrollTo(state, address) {
    return state.setIn(["viewOptions", "topAddressShown"],
        Math.max(0, Math.min(address, Constants.MEMORY_SIZE - 1)));
}

function scrollToPC(state) {
    const pc = state.get("lc3").getIn(["registers", "pc"]);
    return state.setIn(["viewOptions", "topAddressShown"], pc);
}

function scrollBy(state, delta) {
    return state.updateIn(["viewOptions", "topAddressShown"],
        x => Math.max(0, Math.min(x + delta, Constants.MEMORY_SIZE - 1)));
}

function step(state) {
    return state.update("lc3", lc3 => lc3.step());
}

export default function reducer(state = initialState, action) {

    switch (action.type) {
        case "SET_PC":
            return setPC(state, action.newPC);
        case "SET_MEMORY":
            return setMemory(state, action.address, action.value);
        case "SET_REGISTER":
            return setRegister(state, action.name, action.value);
        case "LOAD_PROGRAM":
            return loadProgram(state, action.program);
        case "SCROLL_TO":
            return scrollTo(state, action.address);
        case "SCROLL_TO_PC":
            return scrollToPC(state);
        case "SCROLL_BY":
            return scrollBy(state, action.delta);
        case "STEP":
            return step(state);
    }

    return state;
}

@@ -944,18 +944,30 @@
     
-const pc =
+return scrollTo(state,
  sta
@@ -984,16 +984,8 @@
 3%22).
-getIn(%5B%22
 regi
@@ -993,78 +993,9 @@
 ters
-%22, %22pc%22%5D);%0A    return state.setIn(%5B%22viewOptions%22, %22topAddressShown%22%5D, 
+.
 pc);
@@ -1036,35 +1036,48 @@
 ) %7B%0A    
-return
+const currentAddress =
  state.
-update
+get
 In(%5B%22vie
@@ -1109,82 +1109,60 @@
 wn%22%5D
-,
+);
 %0A    
-    x =%3E Math.max(0, Math.min(x + delta, Constants.MEMORY_SIZE - 1))
+return scrollTo(state, currentAddress + delta
 );%0A%7D

Consolidate SCROLL_TO_PC, SCROLL_BY -> SCROLL_TO