/*
 * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors.
 *
 * 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 org.switchyard.internal;

import java.util.EventObject;

import javax.xml.namespace.QName;

import junit.framework.Assert;

import org.junit.Before;
import org.junit.Test;
import org.switchyard.BaseHandler;
import org.switchyard.MockDomain;
import org.switchyard.Service;
import org.switchyard.ServiceDomain;
import org.switchyard.ServiceReference;
import org.switchyard.event.EventObserver;
import org.switchyard.event.ReferenceRegistrationEvent;
import org.switchyard.event.ReferenceUnregistrationEvent;
import org.switchyard.event.ServiceRegistrationEvent;
import org.switchyard.event.ServiceUnregistrationEvent;
import org.switchyard.event.TransformerAddedEvent;
import org.switchyard.event.TransformerRemovedEvent;
import org.switchyard.event.ValidatorAddedEvent;
import org.switchyard.event.ValidatorRemovedEvent;
import org.switchyard.metadata.InOutService;
import org.switchyard.transform.BaseTransformer;
import org.switchyard.transform.Transformer;
import org.switchyard.validate.BaseValidator;
import org.switchyard.validate.ValidationResult;
import org.switchyard.validate.Validator;

/**
 *  Tests for events generated by the core runtime.
 */
public class EventsTest {

    private ServiceDomain _domain;
    private DummyObserver _observer;
    
    @Before
    public void setUp() throws Exception {
        _domain = new MockDomain();
        _observer = new DummyObserver();
    }
    
    @Test
    public void testTransformerEvents() {
        _domain.addEventObserver(_observer, TransformerAddedEvent.class)
            .addEventObserver(_observer, TransformerRemovedEvent.class);
        Transformer<String, String> t = new BaseTransformer<String, String>() {
            public String transform(String from) {
                return null;
            }
        };
        _domain.getTransformerRegistry().addTransformer(t);
        Assert.assertTrue(_observer.addTransformerCalled);
        _domain.getTransformerRegistry().removeTransformer(t);
        Assert.assertTrue(_observer.removeTransformerCalled);
    }

    @Test
    public void testValidatorEvents() {
        _domain.addEventObserver(_observer, ValidatorAddedEvent.class)
            .addEventObserver(_observer, ValidatorRemovedEvent.class);
        Validator<String> t = new BaseValidator<String>() {
            public ValidationResult validate(String name) {
                return new ValidationResult() {
                    public boolean isValid() {
                        return false;
                    }
                    public String getDetail() {
                        return "error";
                    }
                };
            }
        };
        _domain.getValidatorRegistry().addValidator(t);
        Assert.assertTrue(_observer.addValidatorCalled);
        _domain.getValidatorRegistry().removeValidator(t);
        Assert.assertTrue(_observer.removeValidatorCalled);
    }
    
    @Test
    public void testReferenceEvents() {
        _domain.addEventObserver(_observer, ReferenceRegistrationEvent.class)
            .addEventObserver(_observer, ReferenceUnregistrationEvent.class);
        
        ServiceReference ref = _domain.registerServiceReference(new QName("test"), new InOutService());
        Assert.assertTrue(_observer.referenceRegistrationCalled);
        ref.unregister();
        Assert.assertTrue(_observer.referenceUnregistrationCalled);
    }

    @Test
    public void testServiceEvents() {
        _domain.addEventObserver(_observer, ServiceRegistrationEvent.class)
            .addEventObserver(_observer, ServiceUnregistrationEvent.class);
        
        Service service = _domain.registerService(new QName("test"), new InOutService(), new BaseHandler());
        Assert.assertTrue(_observer.serviceRegistrationCalled);
        service.unregister();
        Assert.assertTrue(_observer.serviceUnregistrationCalled);
    }
}


class DummyObserver implements EventObserver {
    
    public boolean removeTransformerCalled;
    public boolean addTransformerCalled;
    public boolean removeValidatorCalled;
    public boolean addValidatorCalled;
    public boolean referenceRegistrationCalled;
    public boolean referenceUnregistrationCalled;
    public boolean serviceRegistrationCalled;
    public boolean serviceUnregistrationCalled;

    public void notify(EventObject event) {
        if (event instanceof TransformerAddedEvent) {
            addTransformerCalled = true;
        } else if (event instanceof TransformerRemovedEvent) {
            removeTransformerCalled = true;
        } else if (event instanceof ValidatorAddedEvent) {
            addValidatorCalled = true;
        } else if (event instanceof ValidatorRemovedEvent) {
            removeValidatorCalled = true;
        } else if (event instanceof ReferenceRegistrationEvent) {
            referenceRegistrationCalled = true;
        } else if (event instanceof ReferenceUnregistrationEvent) {
            referenceUnregistrationCalled = true;
        } else if (event instanceof ServiceRegistrationEvent) {
            serviceRegistrationCalled = true;
        } else if (event instanceof ServiceUnregistrationEvent) {
            serviceUnregistrationCalled = true;
        }
    }
}