// Copyright 2007, 2008 The Apache Software Foundation
//
// 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.apache.tapestry5.internal.services;

import org.apache.tapestry5.Link;
import org.apache.tapestry5.internal.util.Holder;
import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newList;
import org.apache.tapestry5.services.PersistentFieldChange;
import org.apache.tapestry5.services.Request;
import org.apache.tapestry5.test.TapestryTestCase;
import org.easymock.EasyMock;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.isA;
import org.easymock.IAnswer;
import org.testng.annotations.Test;

import java.util.List;

public class ClientPersistentFieldStorageImplTest extends TapestryTestCase
{
    @Test
    public void no_client_data_in_request()
    {
        Request request = mockRequest(null);
        Link link = mockLink();

        replay();

        ClientPersistentFieldStorage storage = new ClientPersistentFieldStorageImpl(request);

        // Should do nothing.

        storage.updateLink(link);

        verify();
    }

    @SuppressWarnings("unchecked")
    @Test
    public void store_and_restore_a_change()
    {
        Request request = mockRequest(null);
        Link link = mockLink();
        final Holder<String> holder = Holder.create();

        String pageName = "Foo";
        String componentId = "bar.baz";
        String fieldName = "biff";
        Object value = 99;

        // Use an IAnswer to capture the value.

        link.addParameter(eq(ClientPersistentFieldStorageImpl.PARAMETER_NAME), isA(String.class));
        setAnswer(new IAnswer<Void>()
        {
            public Void answer() throws Throwable
            {
                String base64 = (String) EasyMock.getCurrentArguments()[1];

                holder.put(base64);

                return null;
            }
        });

        replay();

        ClientPersistentFieldStorage storage1 = new ClientPersistentFieldStorageImpl(request);

        storage1.postChange(pageName, componentId, fieldName, value);

        List<PersistentFieldChange> changes1 = newList(storage1.gatherFieldChanges(pageName));

        storage1.updateLink(link);

        verify();

        System.out.println(holder.get());

        assertEquals(changes1.size(), 1);
        PersistentFieldChange change1 = changes1.get(0);

        assertEquals(change1.getComponentId(), componentId);
        assertEquals(change1.getFieldName(), fieldName);
        assertEquals(change1.getValue(), value);

        // Now more training ...

        train_getParameter(request, ClientPersistentFieldStorageImpl.PARAMETER_NAME, holder.get());

        replay();

        ClientPersistentFieldStorage storage2 = new ClientPersistentFieldStorageImpl(request);

        List<PersistentFieldChange> changes2 = newList(storage2.gatherFieldChanges(pageName));

        verify();

        assertEquals(changes2.size(), 1);
        PersistentFieldChange change2 = changes2.get(0);

        assertEquals(change2.getComponentId(), componentId);
        assertEquals(change2.getFieldName(), fieldName);
        assertEquals(change2.getValue(), value);

        assertNotSame(change1, change2);
    }

    @Test
    public void multiple_changes()
    {
        Request request = mockRequest(null);
        Link link = mockLink();

        String pageName = "Foo";
        String componentId = "bar.baz";

        link.addParameter(eq(ClientPersistentFieldStorageImpl.PARAMETER_NAME), isA(String.class));

        replay();

        ClientPersistentFieldStorage storage = new ClientPersistentFieldStorageImpl(request);

        for (int k = 0; k < 3; k++)
        {
            for (int i = 0; i < 20; i++)
            {
                // Force some cache collisions ...

                storage.postChange(pageName, componentId, "field" + i, i * k);
            }
        }

        storage.postChange(pageName, null, "field", "foo");
        storage.postChange(pageName, null, "field", "bar");

        storage.updateLink(link);

        verify();
    }

    @Test
    public void null_value_is_a_remove()
    {
        Request request = mockRequest(null);
        Link link = mockLink();

        String pageName = "Foo";
        String componentId = "bar.baz";
        String fieldName = "woops";

        replay();

        ClientPersistentFieldStorage storage = new ClientPersistentFieldStorageImpl(request);

        storage.postChange(pageName, componentId, fieldName, 99);
        storage.postChange(pageName, componentId, fieldName, null);

        storage.updateLink(link);

        assertTrue(storage.gatherFieldChanges(pageName).isEmpty());

        verify();
    }

    /**
     * TAPESTRY-1475
     */
    @Test
    public void discard_changes()
    {
        Request request = mockRequest(null);
        Link link = mockLink();

        String pageName = "Foo";
        String componentId = "bar.baz";
        String fieldName = "woops";

        replay();

        ClientPersistentFieldStorage storage = new ClientPersistentFieldStorageImpl(request);

        storage.postChange(pageName, componentId, fieldName, 99);

        storage.discardChanges(pageName);

        storage.updateLink(link);

        assertTrue(storage.gatherFieldChanges(pageName).isEmpty());

        verify();
    }


    @Test
    public void value_not_serializable()
    {
        Request request = mockRequest(null);

        Object badBody = new Object()
        {
            @Override
            public String toString()
            {
                return "<BadBoy>";
            }
        };

        replay();

        ClientPersistentFieldStorage storage = new ClientPersistentFieldStorageImpl(request);

        try
        {
            storage.postChange("Foo", "bar.baz", "woops", badBody);
            unreachable();
        }
        catch (IllegalArgumentException ex)
        {
            assertEquals(
                    ex.getMessage(),
                    "State persisted on the client must be serializable, but <BadBoy> does not implement the Serializable interface.");
        }

        verify();
    }

    @Test
    public void corrupt_client_data()
    {
        // A cut-n-paste from some previous output, with the full value significantly truncated.
        Request request = mockRequest("H4sIAAAAAAAAAEWQsUoDQRCGJxdDTEwRU2hlZ71pBQ");

        replay();

        ClientPersistentFieldStorage storage = new ClientPersistentFieldStorageImpl(request);

        try
        {
            storage.postChange("Foo", "bar.baz", "woops", 99);
            unreachable();
        }
        catch (RuntimeException ex)
        {
            assertEquals(ex.getMessage(), ServicesMessages.corruptClientState());
            assertNotNull(ex.getCause());
        }

        verify();
    }

    protected final Request mockRequest(String clientData)
    {
        Request request = mockRequest();

        train_getParameter(request, ClientPersistentFieldStorageImpl.PARAMETER_NAME, clientData);

        return request;
    }

}
