/*
 * Copyright 2012 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.requestfactory.shared.impl;

import com.google.gwt.core.client.GWT;
import com.google.gwt.junit.client.GWTTestCase;
import com.google.web.bindery.autobean.shared.AutoBean;
import com.google.web.bindery.autobean.shared.AutoBeanCodex;
import com.google.web.bindery.autobean.shared.AutoBeanUtils;
import com.google.web.bindery.event.shared.SimpleEventBus;
import com.google.web.bindery.requestfactory.gwt.client.DefaultRequestTransport;
import com.google.web.bindery.requestfactory.shared.Receiver;
import com.google.web.bindery.requestfactory.shared.RequestTransport;
import com.google.web.bindery.requestfactory.shared.SimpleFooProxy;
import com.google.web.bindery.requestfactory.shared.SimpleFooRequest;
import com.google.web.bindery.requestfactory.shared.SimpleRequestFactory;
import com.google.web.bindery.requestfactory.shared.SimpleValueProxy;
import com.google.web.bindery.requestfactory.shared.messages.OperationMessage;
import com.google.web.bindery.requestfactory.shared.messages.RequestMessage;

import java.util.Arrays;
import java.util.Collections;

/**
 * Contains a few tests regarding request payload, to make sure we don't send
 * too many things to the server.
 * <p>
 * Uses a special {@link RequestContext} that records the last request payload,
 * then parses and introspects it to see what's really been sent over the wire
 * in relation to what had been enqueued in the request context.
 */
public class RequestPayloadTest extends GWTTestCase {

  /**
   * Records the request payload so it can be re-parsed and analyzed.
   */
  protected static class RecordingRequestTransport implements RequestTransport {
    public String lastRequestPayload;
    private final RequestTransport realTransport;

    public RecordingRequestTransport(RequestTransport realTransport) {
      this.realTransport = realTransport;
    }

    @Override
    public void send(String payload, TransportReceiver receiver) {
      this.lastRequestPayload = payload;
      realTransport.send(payload, receiver);
    }
  }

  protected SimpleRequestFactory factory;
  protected RecordingRequestTransport transport;

  @Override
  public String getModuleName() {
    return "com.google.web.bindery.requestfactory.gwt.RequestFactorySuite";
  }

  /**
   * Tests that no more proxies and property values than necessary are being sent.
   */
  public void testOperationPayload() throws Exception {
    delayTestFinish(5000);

    SimpleFooRequest context = factory.simpleFooRequest();
    context.findSimpleFooById(1L).with("barField", "oneToManyField").fire(
        new Receiver<SimpleFooProxy>() {
          @Override
          public void onSuccess(final SimpleFooProxy response) {
            SimpleFooRequest context = factory.simpleFooRequest();
            final SimpleFooProxy foo = context.edit(response);

            // simply casting 'factory' to AbstractRequestFactory would fail
            // when run as a JRE test.
            final AbstractRequestFactory abstractRequestFactory =
                AutoBeanUtils.getAutoBean(foo).<AbstractRequestContext.State> getTag(
                    Constants.REQUEST_CONTEXT_STATE).requestFactory;
            final String fooTypeToken = abstractRequestFactory.getTypeToken(SimpleFooProxy.class);
            final String valueTypeToken =
                abstractRequestFactory.getTypeToken(SimpleValueProxy.class);

            // Create
            final SimpleValueProxy created = context.create(SimpleValueProxy.class);
            created.setNumber(42);
            created.setString("Hello world!");
            created.setSimpleFoo(foo);
            // Test cycles in value
            created.setSimpleValue(Arrays.asList(created));

            // Set
            foo.setSimpleValue(created);
            foo.setSimpleValues(Collections.singletonList(created));

            context.persistAndReturnSelf().using(foo).with("barField", "oneToManyField",
                "oneToManySetField", "simpleValue", "simpleValues").fire(
                new Receiver<SimpleFooProxy>() {
                  @Override
                  public void onSuccess(SimpleFooProxy response) {
                    RequestMessage requestMessage =
                        AutoBeanCodex.decode(MessageFactoryHolder.FACTORY, RequestMessage.class,
                            transport.lastRequestPayload).as();

                    int seenFoos = 0;
                    int seenValues = 0;
                    for (OperationMessage operationMessage : requestMessage.getOperations()) {
                      if (fooTypeToken.equals(operationMessage.getTypeToken())) {
                        seenFoos++;
                        @SuppressWarnings("unchecked")
                        SimpleProxyId<?> id = (SimpleProxyId<?>) foo.stableId();
                        assertEquals(id.getServerId(), operationMessage.getServerId());
                        assertEquals(2, operationMessage.getPropertyMap().size());
                        assertTrue(operationMessage.getPropertyMap().containsKey("simpleValue"));
                        assertTrue(operationMessage.getPropertyMap().containsKey("simpleValues"));
                      } else if (valueTypeToken.equals(operationMessage.getTypeToken())) {
                        seenValues++;
                        AutoBean<SimpleValueProxy> bean = AutoBeanUtils.getAutoBean(created);
                        SimpleProxyId<?> id = BaseProxyCategory.stableId(bean);
                        assertEquals(id.getClientId(), operationMessage.getClientId());
                        assertEquals(AutoBeanUtils.getAllProperties(bean).keySet(),
                            operationMessage.getPropertyMap().keySet());
                      }
                    }
                    assertTrue(seenFoos > 0);
                    assertTrue(seenValues > 0);

                    // Persist without any change
                    factory.simpleFooRequest().persistAndReturnSelf().using(response).fire(
                        new Receiver<SimpleFooProxy>() {

                          @Override
                          public void onSuccess(SimpleFooProxy response) {
                            RequestMessage requestMessage =
                                AutoBeanCodex.decode(MessageFactoryHolder.FACTORY,
                                    RequestMessage.class, transport.lastRequestPayload).as();

                            int seenFoos = 0;
                            for (OperationMessage operationMessage : requestMessage.getOperations()) {
                              if (fooTypeToken.equals(operationMessage.getTypeToken())) {
                                seenFoos++;
                                assertNull(operationMessage.getPropertyMap());
                              }
                            }
                            assertTrue(seenFoos > 0);

                            finishTest();
                          }
                        });
                  }
                });
          }
        });
  }

  /**
   * Create (without initializing) a new {@link SimpleRequestFactory}.
   */
  protected SimpleRequestFactory createFactory() {
    return GWT.create(SimpleRequestFactory.class);
  }

  /**
   * Create a new {@link RequestTransport}.
   */
  protected RequestTransport createTransport() {
    return new DefaultRequestTransport();
  }

  @Override
  protected void gwtSetUp() throws Exception {
    factory = createFactory();
    transport = new RecordingRequestTransport(createTransport());
    factory.initialize(new SimpleEventBus(), transport);
  }
}
