// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package factory

import (
	"errors"
	"fmt"
	"testing"

	"v.io/v23/context"
	"v.io/v23/discovery"
	"v.io/v23/security"
)

type mock struct {
	numInits, numAdvertises, numScans, numCloses int
	initErr                                      error
}

func (m *mock) init() (discovery.T, error) {
	m.numInits++
	if m.initErr != nil {
		return nil, m.initErr
	}
	return m, nil
}

func (m *mock) Advertise(_ *context.T, _ discovery.Service, _ []security.BlessingPattern) (<-chan struct{}, error) {
	m.numAdvertises++
	return nil, nil
}

func (m *mock) Scan(_ *context.T, _ string) (<-chan discovery.Update, error) {
	m.numScans++
	return nil, nil
}

func (m *mock) Close() {
	m.numCloses++
}

func (m *mock) check(numInits, numAdvertises, numScans, numCloses int) error {
	switch {
	case m.numInits != numInits:
		return fmt.Errorf("expect %d init calls, but got %d times", numInits, m.numInits)
	case m.numAdvertises != numAdvertises:
		return fmt.Errorf("expect %d advertise calls, but got %d times", numAdvertises, m.numAdvertises)
	case m.numScans != numScans:
		return fmt.Errorf("expect %d scan calls, but got %d times", numScans, m.numScans)
	case m.numCloses != numCloses:
		return fmt.Errorf("expect %d close calls, but got %d times", numCloses, m.numCloses)
	}
	return nil
}

func TestLazyFactory(t *testing.T) {
	m := mock{}
	d := newLazyFactory(m.init)

	if err := m.check(0, 0, 0, 0); err != nil {
		t.Error(err)
	}

	for i := 0; i < 3; i++ {
		d.Advertise(nil, discovery.Service{}, nil)
		if err := m.check(1, i+1, i, i); err != nil {
			t.Error(err)
		}

		d.Scan(nil, "")
		if err := m.check(1, i+1, i+1, i); err != nil {
			t.Error(err)
		}

		d.Close()
		if err := m.check(1, i+1, i+1, i+1); err != nil {
			t.Error(err)
		}
	}
}

func TestLazyFactoryClosed(t *testing.T) {
	m := mock{}
	d := newLazyFactory(m.init)

	d.Close()
	if err := m.check(0, 0, 0, 0); err != nil {
		t.Error(err)
	}

	// Closed already; Shouldn't initialize it again.
	if _, err := d.Advertise(nil, discovery.Service{}, nil); err != errClosed {
		t.Errorf("expected an error %v, but got %v", errClosed, err)
	}
	if err := m.check(0, 0, 0, 0); err != nil {
		t.Error(err)
	}

	if _, err := d.Scan(nil, ""); err != errClosed {
		t.Errorf("expected an error %v, but got %v", errClosed, err)
	}
	if err := m.check(0, 0, 0, 0); err != nil {
		t.Error(err)
	}
}

func TestLazyFactoryInitError(t *testing.T) {
	errInit := errors.New("test error")
	m := mock{initErr: errInit}
	d := newLazyFactory(m.init)

	if _, err := d.Advertise(nil, discovery.Service{}, nil); err != errInit {
		t.Errorf("expected an error %v, but got %v", errInit, err)
	}
	if err := m.check(1, 0, 0, 0); err != nil {
		t.Error(err)
	}

	if _, err := d.Scan(nil, ""); err != errInit {
		t.Errorf("expected an error %v, but got %v", errInit, err)
	}
	if err := m.check(1, 0, 0, 0); err != nil {
		t.Error(err)
	}

	d.Close()
	if err := m.check(1, 0, 0, 0); err != nil {
		t.Error(err)
	}
}
