@Ignore("needs to check if finishing creates a proper task")
  @Test
  public void shouldSetSessionEnd() {
    sessionManager.startMobileSession(false);
    triggerMeasurement();

    sessionManager.finishSession(0);

    verify(sessionManager.sessionRepository)
        .save(
            Mockito.argThat(
                new BaseMatcher<Session>() {
                  @Override
                  public boolean matches(Object o) {
                    Session other = (Session) o;
                    long oneSecond = 1000;
                    return new Date().getTime() - other.getEnd().getTime() < oneSecond;
                  }

                  @Override
                  public void describeTo(Description description) {
                    description.appendText("Session with end set");
                  }
                }));
  }
  @Test
  public void shouldNotifyListenersOnSessionClobber() {
    sessionManager.getSession().setId(1234);
    sessionManager.discardSession();

    verify(sessionManager.eventBus).post(Mockito.any(SessionChangeEvent.class));
  }
  @Test
  public void shouldStartASession() {
    sessionManager.startMobileSession(false);

    verify(sessionManager.locationHelper, times(2)).start();
    verify(sessionManager.audioReader).start();
    assertThat(sessionManager.isSessionStarted(), equalTo(true));
  }
  @Test
  public void shouldNotAddMeasurementsToASavedSession() {
    sessionManager.session = new Session();

    triggerMeasurement(10);

    assertThat(sessionManager.getMeasurementStreams().isEmpty(), equalTo(true));
  }
  @Test
  public void shouldNotStopSensorsDuringASession() {
    sessionManager.startMobileSession(false);
    sessionManager.stopSensors();

    verify(sessionManager.locationHelper, never()).stop();
    verify(sessionManager.audioReader, never()).stop();
    assertThat(sessionManager.isSessionStarted(), equalTo(true));
  }
  @Test
  public void shouldStopSensors() {
    sessionManager.startSensors();
    sessionManager.stopSensors();

    verify(sessionManager.audioReader).stop();
    verify(sessionManager.locationHelper).stop();
    assertThat(sessionManager.isSessionStarted(), equalTo(false));
  }
  @Test
  public void shouldJustDeleteNotesIfSessionInProgress() {
    sessionManager.startMobileSession(false);
    Note note = sessionManager.makeANote(null, null, null);

    sessionManager.deleteNote(note);

    assertThat(sessionManager.getNotes(), not(hasItem(note)));
  }
  @Test
  public void shouldAllowAccessToAParticularStream() {
    sessionManager.startMobileSession(false);

    triggerMeasurement();

    MeasurementStream expected = Iterables.getOnlyElement(sessionManager.getMeasurementStreams());
    assertThat(sessionManager.getMeasurementStream("LHC") == expected, equalTo(true));
  }
  @Test
  public void shouldCreateOnlyOneStreamPerSensor() {
    sessionManager.startMobileSession(false);

    triggerMeasurement();
    triggerMeasurement();

    assertThat(sessionManager.getMeasurementStreams().size(), equalTo(1));
  }
  @Test
  public void shouldMarkNotesToBeDeletedForSavedSessions() {
    sessionManager.session = mock(Session.class);
    when(sessionManager.session.getId()).thenReturn(1234L);
    Note note = new Note(null, null, location, null, 10);

    sessionManager.deleteNote(note);

    verify(sessionManager.session).deleteNote(note);
  }
  @Test
  public void measurements_withoutLocation_should_get_a_fake() {
    sessionManager.startMobileSession(false);
    sessionManager.session.setLocationless(true);
    when(sessionManager.locationHelper.getLastLocation()).thenReturn(null);

    triggerMeasurement();

    assertThat(sessionManager.getMeasurementStreams().isEmpty(), equalTo(false));
    assertThat(sessionManager.getSession().isLocationless(), equalTo(true));
  }
  @Test
  public void shouldStoreMeasurements() {
    sessionManager.startMobileSession(false);

    triggerMeasurement(22);

    Measurement expected = new Measurement(location.getLatitude(), location.getLongitude(), 22);
    org.fest.assertions.Assertions.assertThat(
            sessionManager.getMeasurementStream("LHC").getMeasurements())
        .contains(expected);
  }
  @Test
  public void shouldStoreLastMeasurementForEachSensor() {
    triggerMeasurement("LHC", 150);
    triggerMeasurement("LHC2", 123);

    Sensor sensor2 = mock(Sensor.class);
    when(sensor2.getSensorName()).thenReturn("LHC2");

    assertThat(sessionManager.getNow(sensor), equalTo(150.0));
    assertThat(sessionManager.getNow(sensor2), equalTo(123.0));
  }
  @Ignore("Fix session persistence")
  @Test
  public void shouldStopASession() {
    triggerMeasurement(11);
    sessionManager.finishSession(0);

    verify(sessionManager.audioReader, never()).stop();
    verify(sessionManager.locationHelper).stop();
    verify(sessionManager.sessionRepository).save(Mockito.any(Session.class));
    assertThat(sessionManager.isSessionStarted(), equalTo(false));
  }
  @Test
  public void shouldCreateMeasurementStreams() {
    sessionManager.startMobileSession(false);

    triggerMeasurement();

    MeasurementStream expected = lastEvent.stream();
    Collection<MeasurementStream> streams = sessionManager.getMeasurementStreams();

    assertThat(streams, hasItem(expected));
  }
  @Test
  public void afterDeletingNotesShouldHaveNewNumbers() {
    sessionManager.startMobileSession(false);
    Note note1 = sessionManager.makeANote(null, "Note1", null);
    Note note2 = sessionManager.makeANote(null, "Note2", null);

    sessionManager.deleteNote(note1);
    Note note3 = sessionManager.makeANote(null, "Note3", null);

    assertThat(note3.getNumber(), not(equalTo(note2.getNumber())));
  }
  @Test
  public void shouldCreateAStreamForEachSensor() {
    sessionManager.startMobileSession(false);

    triggerMeasurement();
    SensorEvent event =
        new SensorEvent("CERN", "LHC2", "Siggh boson", "SB", "number", "#", 1, 2, 3, 4, 5, 10);
    sessionManager.onEvent(event);

    MeasurementStream expected = event.stream();
    assertThat(sessionManager.getMeasurementStreams(), hasItem(expected));
  }
  @Test
  public void stopSession_should_changeRecordingState() throws Exception {
    // given
    sessionManager.startMobileSession(false);

    // when
    sessionManager.stopSession();

    // then
    org.fest.assertions.Assertions.assertThat(sessionManager.state.recording().isRecording())
        .isFalse();
  }
  @Test
  public void should_not_crashOnDeletedSensor() throws Exception {
    // given
    SensorEvent event =
        new SensorEvent("CERN", "LHC", "Siggh boson", "SB", "number", "#", 1, 2, 3, 4, 5, 10);
    sessionManager.onEvent(event);

    // when
    sessionManager.deleteSensorStream(event.getSensorName());

    // then (shouldn't crash)
    sessionManager.onEvent(event);
  }
  @Test
  public void shouldDiscardASession() {
    sessionManager.startMobileSession(false);
    sessionManager.getSession().setId(1234);

    triggerMeasurement(13.5);
    sessionManager.discardSession();

    verify(sessionManager.audioReader, never()).stop();
    verify(sessionManager.locationHelper).stop();
    verify(sessionManager.sessionRepository, never()).save(Mockito.any(Session.class));
    assertThat(sessionManager.getMeasurementStreams().isEmpty(), equalTo(true));
    assertThat(sessionManager.isSessionStarted(), equalTo(false));
  }
  private void mockSensors() {
    sessionManager.locationHelper = mock(LocationHelper.class);
    sessionManager.audioReader = mock(SimpleAudioReader.class);
    sessionManager.externalSensors = mock(ExternalSensors.class);
    sessionManager.eventBus = mock(EventBus.class);
    sessionManager.sensorManager = mock(SensorManager.class);

    sensor = mock(Sensor.class);
    when(sensor.isEnabled()).thenReturn(true);
    when(sensor.getSensorName()).thenReturn("LHC");

    when(sessionManager.locationHelper.getLastLocation()).thenReturn(location);
    when(sessionManager.sensorManager.getSensorByName(Mockito.any(String.class)))
        .thenReturn(sensor);
  }
  @Ignore("needs to check if finishing creates a proper task")
  @Test
  public void shouldSaveAdditionalData() {
    triggerMeasurement(100);
    sessionManager.finishSession(0);

    verify(sessionManager.sessionRepository)
        .save(
            Mockito.argThat(
                new BaseMatcher<Session>() {
                  @Override
                  public boolean matches(Object o) {
                    Session session = (Session) o;
                    return session.getCalibration() == 123
                        && session.getOffset60DB() == 432
                        && "1.1.1".equals(session.getOSVersion())
                        && "very old".equals(session.getPhoneModel());
                  }

                  @Override
                  public void describeTo(Description description) {
                    description.appendText("Session with additional data set");
                  }
                }));
  }
  @Test
  public void shouldStartSensors() {
    sessionManager.startSensors();

    verify(sessionManager.locationHelper).start();
    verify(sessionManager.audioReader).start();
    verify(sessionManager.externalSensors).start();
  }
  @Test
  public void shouldOnlyStartSensorsOnce() {
    sessionManager.startSensors();
    sessionManager.startSensors();

    verify(sessionManager.locationHelper, atMost(1)).start();
    verify(sessionManager.audioReader, atMost(1)).start();
  }
  @Test
  public void shouldSkipMeasurementsFromDisabledStreams() {
    sessionManager.state.recording().startRecording();
    when(sensor.isEnabled()).thenReturn(false);

    triggerMeasurement();

    assertThat(sessionManager.getMeasurementStreams().isEmpty(), equalTo(true));
  }
  @Test
  public void shouldSetSessionStart() {
    sessionManager.startMobileSession(false);

    int oneSecond = 1000;
    assertThat(
        new Date().getTime() - sessionManager.session.getStart().getTime() < oneSecond,
        equalTo(true));
  }
  @Before
  public void setUp() throws Exception {
    location = new Location(LocationManager.GPS_PROVIDER);
    location.setLatitude(50);
    location.setLongitude(20);
    sessionManager.sessionRepository = mock(SessionRepository.class);

    mockSensors();
    progressListener = mock(ProgressListener.class);
  }
  @Test
  public void shouldProvidePeakForEachStream() {
    MeasurementStream stream = mock(MeasurementStream.class);
    when(stream.getPeak()).thenReturn(11.0);
    String name = sensor.getSensorName();
    when(stream.getSensorName()).thenReturn(name);
    sessionManager.session.add(stream);

    assertThat(sessionManager.getPeak(sensor), equalTo(11.0));
  }
  @Test
  public void startSession_should_be_indicated_in_recording_state() throws Exception {
    // given

    // when
    sessionManager.startMobileSession(false);

    // then
    org.fest.assertions.Assertions.assertThat(sessionManager.state.recording().isRecording())
        .isTrue();
  }
  @Test
  public void isCalibrating() {
    sessionManager = spy(sessionManager);
    doReturn(new Session())
        .when(sessionManager.sessionRepository)
        .loadFully(anyLong(), Matchers.<ProgressListener>anyObject());

    sessionManager.loadSession(0, progressListener);

    verify(sessionManager, atLeastOnce()).setSession(any(Session.class));
  }