/*
 * 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;

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

  class SourcedHandler implements FooEvent.Handler {
    final String expectedSource;

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

    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;
    }

    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() {
        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() {
      public void onFoo(FooEvent event) {
        add(this);
      }
    };
    FooEvent.Handler one = new FooEvent.Handler() {
      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();

      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() {
      public void onFoo(FooEvent event) {
        add(this);
      }

      @Override
      public String toString() {
        return "two";
      }
    };
    FooEvent.Handler one = new FooEvent.Handler() {
      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() {
      public void execute() {
        eventBus.addHandler(null, fooHandler1);
      }
    });

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

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

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

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

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

    FooEvent.Handler handler = new FooEvent.Handler() {
      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);

      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() {
      public void onFoo(FooEvent event) {
        add(this);
      }
    };
    final FooEvent.Handler handler1 = new FooEvent.Handler() {
      public void onFoo(FooEvent event) {
        assertNotFired(handler0);
        add(this);
      }
    };
    final FooEvent.Handler handler2 = new FooEvent.Handler() {
      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 */
    }
  }
}
