/*
 * Copyright 2011 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.google.web.bindery.event.shared;

import com.google.web.bindery.event.shared.testing.CountingEventBus;

import junit.framework.AssertionFailedError;

import java.util.Set;

/**
 * Eponymous unit test.
 */
public class SimpleEventBusTest extends EventBusTestBase {

  interface Command {
    void execute();
  }

  class ShyHandler implements FooEvent.Handler {
    HandlerRegistration r;

    @Override
    public void onFoo(FooEvent event) {
      add(this);
      r.removeHandler();
    }
  }

  class SourcedHandler implements FooEvent.Handler {
    final String expectedSource;

    SourcedHandler(String source) {
      this.expectedSource = source;
    }

    @Override
    public void onFoo(FooEvent event) {
      add(this);
      assertEquals(expectedSource, event.getSource());
    }
  }

  static class ThrowingHandler implements FooEvent.Handler {
    private final RuntimeException e;

    public ThrowingHandler(RuntimeException e) {
      this.e = e;
    }

    @Override
    public void onFoo(FooEvent event) {
      throw e;
    }
  }

  public void testAddAndRemoveHandlers() {
    CountingEventBus eventBus = new CountingEventBus(new SimpleEventBus());
    FooEvent.register(eventBus, fooHandler1);
    FooEvent.register(eventBus, fooHandler2);
    HandlerRegistration reg1 = FooEvent.register(eventBus, adaptor1);
    eventBus.fireEvent(new FooEvent());
    assertEquals(3, eventBus.getCount(FooEvent.TYPE));
    assertFired(fooHandler1, fooHandler2, adaptor1);
    FooEvent.register(eventBus, fooHandler3);
    assertEquals(4, eventBus.getCount(FooEvent.TYPE));

    FooEvent.register(eventBus, fooHandler1);
    FooEvent.register(eventBus, fooHandler2);
    HandlerRegistration reg2 = FooEvent.register(eventBus, adaptor1);

    /*
     * You can indeed add handlers twice, they will only be removed one at a
     * time though.
     */
    assertEquals(7, eventBus.getCount(FooEvent.TYPE));
    eventBus.addHandler(BarEvent.TYPE, adaptor1);
    eventBus.addHandler(BarEvent.TYPE, barHandler1);
    eventBus.addHandler(BarEvent.TYPE, barHandler2);

    assertEquals(7, eventBus.getCount(FooEvent.TYPE));
    assertEquals(3, eventBus.getCount(BarEvent.TYPE));

    reset();
    eventBus.fireEvent(new FooEvent());
    assertFired(fooHandler1, fooHandler2, fooHandler3, adaptor1);
    assertNotFired(barHandler1, barHandler2);

    // Gets rid of first instance.
    reg1.removeHandler();
    eventBus.fireEvent(new FooEvent());
    assertFired(fooHandler1, fooHandler2, fooHandler3, adaptor1);
    assertNotFired(barHandler1, barHandler2);

    // Gets rid of second instance.
    reg2.removeHandler();
    reset();
    eventBus.fireEvent(new FooEvent());

    assertFired(fooHandler1, fooHandler2, fooHandler3);
    assertNotFired(adaptor1, barHandler1, barHandler2);

    // Checks to see if barHandler events are still working.
    reset();
    eventBus.fireEvent(new BarEvent());

    assertNotFired(fooHandler1, fooHandler2, fooHandler3);
    assertFired(barHandler1, barHandler2, adaptor1);
  }

  public void testAssertThrowsNpe() {
    final SimpleEventBus eventBus = new SimpleEventBus();

    try {
      assertThrowsNpe(new Command() {
        @Override
        public void execute() {
          FooEvent.register(eventBus, fooHandler1);
        }
      });
      fail("expected AssertionFailedError");
    } catch (AssertionFailedError e) {
      /* pass */
    }
  }

  public void testConcurrentAdd() {
    final SimpleEventBus eventBus = new SimpleEventBus();
    final FooEvent.Handler two = new FooEvent.Handler() {
      @Override
      public void onFoo(FooEvent event) {
        add(this);
      }
    };
    FooEvent.Handler one = new FooEvent.Handler() {
      @Override
      public void onFoo(FooEvent event) {
        FooEvent.register(eventBus, two);
        add(this);
      }
    };
    FooEvent.register(eventBus, one);
    FooEvent.register(eventBus, fooHandler1);
    FooEvent.register(eventBus, fooHandler2);
    FooEvent.register(eventBus, fooHandler3);
    eventBus.fireEvent(new FooEvent());
    assertFired(one, fooHandler1, fooHandler2, fooHandler3);
    assertNotFired(two);

    reset();
    eventBus.fireEvent(new FooEvent());
    assertFired(one, two, fooHandler1, fooHandler2, fooHandler3);
  }

  public void testConcurrentAddAfterRemoveIsNotClobbered() {
    final SimpleEventBus eventBus = new SimpleEventBus();

    FooEvent.Handler one = new FooEvent.Handler() {
      HandlerRegistration reg = addIt();

      @Override
      public void onFoo(FooEvent event) {
        reg.removeHandler();
        addIt();
        add(this);
      }

      private HandlerRegistration addIt() {
        return FooEvent.register(eventBus, fooHandler1);
      }
    };

    FooEvent.register(eventBus, one);

    eventBus.fireEvent(new FooEvent());
    assertFired(one);

    reset();

    eventBus.fireEvent(new FooEvent());
    assertFired(one, fooHandler1);
  }

  public void testConcurrentAddAndRemoveByNastyUsersTryingToHurtUs() {
    final SimpleEventBus eventBus = new SimpleEventBus();
    final FooEvent.Handler two = new FooEvent.Handler() {
      @Override
      public void onFoo(FooEvent event) {
        add(this);
      }

      @Override
      public String toString() {
        return "two";
      }
    };
    FooEvent.Handler one = new FooEvent.Handler() {
      @Override
      public void onFoo(FooEvent event) {
        FooEvent.register(eventBus, two).removeHandler();
        add(this);
      }

      @Override
      public String toString() {
        return "one";
      }
    };
    FooEvent.register(eventBus, one);
    FooEvent.register(eventBus, fooHandler1);
    FooEvent.register(eventBus, fooHandler2);
    FooEvent.register(eventBus, fooHandler3);
    eventBus.fireEvent(new FooEvent());
    assertFired(one, fooHandler1, fooHandler2, fooHandler3);
    assertNotFired(two);

    reset();
    eventBus.fireEvent(new FooEvent());
    assertFired(one, fooHandler1, fooHandler2, fooHandler3);
    assertNotFired(two);
  }

  public void testConcurrentRemove() {
    final SimpleEventBus eventBus = new SimpleEventBus();

    ShyHandler h = new ShyHandler();

    FooEvent.register(eventBus, fooHandler1);
    h.r = FooEvent.register(eventBus, h);
    FooEvent.register(eventBus, fooHandler2);
    FooEvent.register(eventBus, fooHandler3);

    eventBus.fireEvent(new FooEvent());
    assertFired(h, fooHandler1, fooHandler2, fooHandler3);
    reset();
    eventBus.fireEvent(new FooEvent());
    assertFired(fooHandler1, fooHandler2, fooHandler3);
    assertNotFired(h);
  }

  public void testFromSource() {
    final SimpleEventBus eventBus = new SimpleEventBus();

    SourcedHandler global = new SourcedHandler("able");
    SourcedHandler able = new SourcedHandler("able");
    SourcedHandler baker = new SourcedHandler("baker");

    FooEvent.register(eventBus, global);
    FooEvent.register(eventBus, "able", able);
    FooEvent.register(eventBus, "baker", baker);

    eventBus.fireEventFromSource(new FooEvent(), "able");
    assertFired(global, able);
    assertNotFired(baker);
  }

  public void testHandlersThrow() {
    RuntimeException exception1 = new RuntimeException("first exception");
    RuntimeException exception2 = new RuntimeException("second exception");

    final SimpleEventBus eventBus = new SimpleEventBus();

    FooEvent.register(eventBus, fooHandler1);
    FooEvent.register(eventBus, new ThrowingHandler(exception1));
    FooEvent.register(eventBus, fooHandler2);
    FooEvent.register(eventBus, new ThrowingHandler(exception2));
    FooEvent.register(eventBus, fooHandler3);

    FooEvent event = new FooEvent();

    try {
      eventBus.fireEvent(event);
      fail("eventBus should have thrown");
    } catch (UmbrellaException e) {
      Set<Throwable> causes = e.getCauses();
      assertEquals("Exception should wrap the two thrown exceptions", 2, causes.size());
      assertTrue("First exception should be under the umbrella", causes.contains(exception1));
      assertTrue("Second exception should be under the umbrella", causes.contains(exception2));
    }

    /*
     * Exception should not have prevented all three mouse handlers from getting
     * the event.
     */
    assertFired(fooHandler1, fooHandler2, fooHandler3);
  }
  
  public void testNoDoubleRemove() {
    final SimpleEventBus eventBus = new SimpleEventBus();
    HandlerRegistration reg = FooEvent.register(eventBus, fooHandler1);
    reg.removeHandler();
    reg.removeHandler(); // should not throw
  }

  public void testNoSource() {
    final SimpleEventBus eventBus = new SimpleEventBus();

    SourcedHandler global = new SourcedHandler(null);
    SourcedHandler able = new SourcedHandler("able");
    SourcedHandler baker = new SourcedHandler("baker");

    FooEvent.register(eventBus, global);
    FooEvent.register(eventBus, "able", able);
    FooEvent.register(eventBus, "baker", baker);

    eventBus.fireEvent(new FooEvent());
    assertFired(global);
    assertNotFired(able, baker);
  }

  public void testNullChecks() {
    final SimpleEventBus eventBus = new SimpleEventBus();
    assertThrowsNpe(new Command() {
      @Override
      public void execute() {
        eventBus.addHandler(null, fooHandler1);
      }
    });

    assertThrowsNpe(new Command() {
      @Override
      public void execute() {
        FooEvent.register(eventBus, "foo", null);
      }
    });
    assertThrowsNpe(new Command() {
      @Override
      public void execute() {
        FooEvent.register(eventBus, null, fooHandler1);
      }
    });
    assertThrowsNpe(new Command() {
      @Override
      public void execute() {
        eventBus.addHandlerToSource(null, "foo", fooHandler1);
      }
    });

    assertThrowsNpe(new Command() {
      @Override
      public void execute() {
        eventBus.fireEvent(null);
      }
    });

    assertThrowsNpe(new Command() {
      @Override
      public void execute() {
        eventBus.fireEventFromSource(null, "");
      }
    });

    assertThrowsNpe(new Command() {
      @Override
      public void execute() {
        eventBus.fireEventFromSource(new FooEvent() {
        }, null);
      }
    });
    assertThrowsNpe(new Command() {
      @Override
      public void execute() {
        eventBus.fireEventFromSource(null, "baker");
      }
    });
  }

  public void testNullSourceOkay() {
    SimpleEventBus reg = new SimpleEventBus();

    FooEvent.Handler handler = new FooEvent.Handler() {
      @Override
      public void onFoo(FooEvent event) {
        add(this);
        assertNull(event.getSource());
      }
    };
    reg.addHandler(FooEvent.TYPE, handler);
    reg.fireEvent(new FooEvent());
    assertFired(handler);
  }

  public void testRemoveSelf() {
    final SimpleEventBus eventBus = new SimpleEventBus();

    FooEvent.Handler h = new FooEvent.Handler() {
      HandlerRegistration reg = FooEvent.register(eventBus, this);

      @Override
      public void onFoo(FooEvent event) {
        add(this);
        reg.removeHandler();
      }
    };

    eventBus.fireEvent(new FooEvent());
    assertFired(h);

    reset();

    eventBus.fireEvent(new FooEvent());
    assertNotFired(h);
  }

  public void testReverseOrder() {
    @SuppressWarnings("deprecation")
    final SimpleEventBus eventBus = new SimpleEventBus(true);
    final FooEvent.Handler handler0 = new FooEvent.Handler() {
      @Override
      public void onFoo(FooEvent event) {
        add(this);
      }
    };
    final FooEvent.Handler handler1 = new FooEvent.Handler() {
      @Override
      public void onFoo(FooEvent event) {
        assertNotFired(handler0);
        add(this);
      }
    };
    final FooEvent.Handler handler2 = new FooEvent.Handler() {
      @Override
      public void onFoo(FooEvent event) {
        assertNotFired(handler0, handler1);
        add(this);
      }
    };
    FooEvent.register(eventBus, handler0);
    FooEvent.register(eventBus, handler1);
    FooEvent.register(eventBus, handler2);

    reset();
    eventBus.fireEvent(new FooEvent());
    assertFired(handler0, handler1, handler2);
  }

  private void assertThrowsNpe(Command command) {
    try {
      command.execute();
      fail("expected NullPointerException");
    } catch (NullPointerException e) {
      /* pass */
    }
  }
}
