// Copyright (C) 2019 The Android Open Source Project
//
// 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.googlesource.gerrit.plugins.websession.broker;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.gerritforge.gerrit.eventbroker.BrokerApi;
import com.gerritforge.gerrit.eventbroker.EventMessage;
import com.gerritforge.gerrit.eventbroker.EventMessage.Header;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.gerrit.entities.Account;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.httpd.FakeWebSessionVal;
import com.google.gerrit.httpd.WebSessionManager.Val;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.config.PluginConfig;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.events.Event;
import com.googlesource.gerrit.plugins.websession.broker.BrokerBasedWebSessionCache.WebSessionEvent;
import com.googlesource.gerrit.plugins.websession.broker.BrokerBasedWebSessionCache.WebSessionEvent.Operation;
import com.googlesource.gerrit.plugins.websession.broker.log.WebSessionLogger;
import com.googlesource.gerrit.plugins.websession.broker.util.TimeMachine;
import java.time.Instant;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class BrokerBasedWebSessionCacheTest {

  private static final int DEFAULT_ACCOUNT_ID = 1000000;
  private static final String KEY = "aSceprtma6B0qZ0hKxXHvQ5iyfUhCcFXxG";
  private static Val VAL = FakeWebSessionVal.getVal(Account.id(1), ExternalId.Key.parse("foo:bar"));
  private static final String PLUGIN_NAME = "websession-broker";

  private byte[] emptyPayload = new byte[] {-84, -19, 0, 5, 112};
  byte[] defaultPayload =
      new byte[] {
        -84, -19, 0, 5, 115, 114, 0, 45, 99, 111, 109, 46, 103, 111, 111, 103, 108, 101, 46, 103,
        101, 114, 114, 105, 116, 46, 104, 116, 116, 112, 100, 46, 87, 101, 98, 83, 101, 115, 115,
        105, 111, 110, 77, 97, 110, 97, 103, 101, 114, 36, 86, 97, 108, 0, 0, 0, 0, 0, 0, 0, 2, 3,
        0, 0, 120, 112, 119, 97, 1, -64, -124, 61, 2, 0, 0, 1, 111, 13, -8, 90, 7, 3, 0, 5, 34, 97,
        83, 99, 101, 112, 114, 113, 86, 87, 54, 85, 79, 45, 88, 51, 107, 51, 116, 102, 85, 109, 86,
        103, 82, 73, 90, 56, 53, 99, 99, 52, 71, 114, 87, 6, 0, 0, 1, 111, 16, 84, -103, -121, 7,
        34, 97, 83, 99, 101, 112, 114, 114, 82, 103, 119, 49, 71, 110, 90, 56, 122, 54, 49, 49, 86,
        52, 121, 110, 65, 100, 110, 113, 99, 68, 45, 105, 99, 75, 97, 0, 120
      };

  ExecutorService executorServce = MoreExecutors.newDirectExecutorService();

  @Mock BrokerApi brokerApi;
  Cache<String, Val> cache;
  @Mock TimeMachine timeMachine;
  @Mock PluginConfigFactory cfg;
  @Mock PluginConfig pluginConfig;
  @Mock WebSessionLogger webSessionLogger;
  @Captor ArgumentCaptor<EventMessage> eventCaptor;
  @Captor ArgumentCaptor<Val> valCaptor;

  BrokerBasedWebSessionCache objectUnderTest;

  @Before
  public void setup() {
    cache = CacheBuilder.newBuilder().build();
    when(pluginConfig.getString("webSessionTopic", "gerrit_web_session"))
        .thenReturn("gerrit_web_session");
    when(cfg.getFromGerritConfig(PLUGIN_NAME)).thenReturn(pluginConfig);
    when(timeMachine.now()).thenReturn(Instant.EPOCH);
    DynamicItem<BrokerApi> item = DynamicItem.itemOf(BrokerApi.class, brokerApi);
    objectUnderTest =
        new BrokerBasedWebSessionCache(
            cache, item, timeMachine, cfg, PLUGIN_NAME, webSessionLogger, executorServce);
  }

  @Test
  public void shouldPublishMessageWhenLoginEvent() {
    EventMessage eventMessage = createEventMessage();
    Val value = createVal(eventMessage);
    when(brokerApi.newMessage(any(UUID.class), any(Event.class))).thenReturn(eventMessage);

    objectUnderTest.put(KEY, value);
    verify(brokerApi, times(1)).send(anyString(), eventCaptor.capture());

    assertThat(eventCaptor.getValue().getEvent()).isNotNull();
    WebSessionEvent event = (WebSessionEvent) eventCaptor.getValue().getEvent();
    assertThat(event.operation).isEqualTo(WebSessionEvent.Operation.ADD);
    assertThat(event.key).isEqualTo(KEY);
    assertThat(event.payload).isEqualTo(defaultPayload);
  }

  @Test
  public void shouldPublishMessageWhenLogoutEvent() {
    EventMessage eventMessage = createEventMessage(emptyPayload, Operation.REMOVE);
    when(brokerApi.newMessage(any(UUID.class), any(Event.class))).thenReturn(eventMessage);

    objectUnderTest.invalidate(KEY);

    verify(brokerApi, times(1)).send(anyString(), eventCaptor.capture());

    assertThat(eventCaptor.getValue().getEvent()).isNotNull();
    WebSessionEvent event = (WebSessionEvent) eventCaptor.getValue().getEvent();
    assertThat(event.operation).isEqualTo(WebSessionEvent.Operation.REMOVE);
    assertThat(event.key).isEqualTo(KEY);
    assertThat(event.payload).isEqualTo(emptyPayload);
  }

  @Test
  public void shouldUpdateCacheWhenLoginMessageReceived() {
    EventMessage eventMessage = createEventMessage();

    objectUnderTest.processMessage(eventMessage);

    Val val = cache.getIfPresent(eventMessageKey(eventMessage));
    assertThat(val).isNotNull();
    assertThat(val.getAccountId().get()).isEqualTo(DEFAULT_ACCOUNT_ID);
  }

  @Test
  public void shouldUpdateCacheWhenLogoutMessageReceived() {
    EventMessage eventMessage = createEventMessage(emptyPayload, Operation.REMOVE);
    cache.put(KEY, VAL);

    objectUnderTest.processMessage(eventMessage);

    assertThat(cache.getIfPresent(KEY)).isNull();
  }

  @Test
  public void shouldCleanupExpiredSessions() {
    when(timeMachine.now()).thenReturn(Instant.MIN, Instant.MAX);

    EventMessage eventMessage = createEventMessage();

    objectUnderTest.processMessage(eventMessage);

    Val val = cache.getIfPresent(eventMessageKey(eventMessage));
    assertThat(val).isNotNull();

    objectUnderTest.cleanUp();

    assertThat(cache.getIfPresent(eventMessageKey(eventMessage))).isNull();
  }

  private Val createVal(EventMessage message) {
    WebSessionEvent event = (WebSessionEvent) message.getEvent();

    objectUnderTest.processMessage(message);
    return cache.getIfPresent(event.key);
  }

  private EventMessage createEventMessage() {

    return createEventMessage(defaultPayload, Operation.ADD);
  }

  private String eventMessageKey(EventMessage eventMessage) {
    WebSessionEvent sessionEvent = (WebSessionEvent) eventMessage.getEvent();
    return sessionEvent.key;
  }

  private EventMessage createEventMessage(byte[] payload, Operation operation) {

    Header header =
        new Header(
            UUID.fromString("7cb80dbe-65c4-4f2c-84de-580d98199d4a"),
            UUID.fromString("97711495-1013-414e-bfd2-44776787520d"));
    WebSessionEvent event = new WebSessionEvent(KEY, payload, operation);
    return new EventMessage(header, event);
  }
}
