import test from 'ava';
import State from '../src/state';

const TEST_TIMEOUT = 100;

test('get and set', t => {
  const state = new State();
  state.set('a.b', { c: { d: 1 } });

  t.deepEqual(state.get(), { a: { b: { c: { d: 1 } } } });
  t.deepEqual(state.get(''), { a: { b: { c: { d: 1 } } } });
  t.deepEqual(state.get('a'), { b: { c: { d: 1 } } });
  t.deepEqual(state.get('a.b'), { c: { d: 1 } });
  t.deepEqual(state.get('a.b.c'), { d: 1 });
  t.deepEqual(state.get('a.b.c.d'), 1);
});

test('undefined', t => {
  const state = new State();
  t.is(state.get(), undefined);
  t.is(state.get('not.fount'), undefined);
});

test('cursor get', t => {
  const state = new State();
  state.set({
    a: {
      b: {
        c: 1,
      },
    },
  });
  t.is(state.cursor().get(), state.get());
  t.is(state.cursor('a').get(), state.get('a'));
  t.is(state.cursor('a').get('b'), state.get('a.b'));
  t.is(state.cursor('a').cursor('b').get(), state.get('a.b'));
  t.true(state.cursor('a') instanceof State);
});

test('cursor set', t => {
  const state = new State();
  const cursorState = state.cursor('a').cursor('b');
  cursorState.set({ c: { d: 1 } });
  cursorState.set('c.e', 2);
  t.deepEqual(state.get(), { a: { b: { c: { d: 1, e: 2 } } } });
});

test.cb('event emit', t => {
  t.plan(4);
  const state = new State();
  const handler = state.on('change', () => t.pass());
  // should emit
  state.set('', 1);
  state.set('a', 1);
  state.set('a.b', 1);
  state.set('c.d', 1);
  // remove listener
  handler();
  state.set('', 1);
  setTimeout(() => {
    t.end();
  }, TEST_TIMEOUT);
});

test.cb('event emit with cursor', t => {
  t.plan(4);
  const state = new State();
  state.cursor('a').on('change', () => t.pass());
  // should emit
  state.set('', 1);
  state.set('a', 1);
  state.set('a.b', 1);
  state.cursor('a').set('c', 1);
  // should not emit
  state.set('c.d', 1);
  setTimeout(() => {
    t.end();
  }, TEST_TIMEOUT);
});

test.cb('set path with dot', t => {
  t.plan(5);
  const state = new State();
  state.cursor('a').on('change', () => t.pass());
  // should emit
  state.set('', 1);
  state.set('a', 1);
  state.set('a.b', 1);
  state.cursor('a').set('c', 1);
  state.set(['a', 'b.c'], 1);
  // should not emit
  state.set(['a.d'], 1);
  state.set(['a.e', 'f'], 1);
  setTimeout(() => {
    t.end();
  }, TEST_TIMEOUT);
});

test.cb('listen path with dot', t => {
  t.plan(3);
  const state = new State();
  state.cursor(['a.b']).on('change', () => t.pass());
  // should emit
  state.set('', 1);
  state.set(['a.b'], 1);
  state.set(['a.b', 'c'], 1);
  // should not emit
  state.set('a', 1);
  state.set('a.b', 1);
  setTimeout(() => {
    t.end();
  }, TEST_TIMEOUT);
});

@@ -1265,20 +1265,33 @@
 ('event 
-emit
+listen and cancel
 ', t =%3E 
@@ -1513,16 +1513,16 @@
 istener%0A
-
   handle
@@ -1597,32 +1597,417 @@
 _TIMEOUT);%0A%7D);%0A%0A
+test.cb('event listen and off', t =%3E %7B%0A  t.plan(4);%0A  const state = new State();%0A  const callback = () =%3E t.pass();%0A  state.on('change', callback);%0A  // should emit%0A  state.set('', 1);%0A  state.set('a', 1);%0A  state.set('a.b', 1);%0A  state.set('c.d', 1);%0A  // remove listener%0A  state.off('change', callback);%0A  state.set('', 1);%0A  setTimeout(() =%3E %7B%0A    t.end();%0A  %7D, TEST_TIMEOUT);%0A%7D);%0A%0A
 test.cb('event e

fix test for event off