package devices

import (
	"sync"

	"code.secondbit.org/uuid.hg"
	"golang.org/x/net/context"
)

type Memstore struct {
	devices map[string]Device
	lock    sync.RWMutex
}

func NewMemstore() *Memstore {
	return &Memstore{
		devices: map[string]Device{},
	}
}

func (m *Memstore) GetDevices(ids []uuid.ID, c context.Context) (map[string]Device, error) {
	m.lock.RLock()
	defer m.lock.RUnlock()

	results := map[string]Device{}

	for _, id := range ids {
		device, ok := m.devices[id.String()]
		if !ok {
			continue
		}
		results[id.String()] = device
	}
	return results, nil
}

func (m *Memstore) UpdateDevice(change DeviceChange, c context.Context) error {
	m.lock.Lock()
	defer m.lock.Unlock()

	device, ok := m.devices[change.DeviceID.String()]
	if !ok {
		return nil // TODO: return an error
	}

	device = ApplyChange(device, change)
	m.devices[change.DeviceID.String()] = device

	return nil
}

func (m *Memstore) DeleteDevices(id []uuid.ID, c context.Context) error {
	return nil
}

func (m *Memstore) CreateDevices(devices []Device, c context.Context) error {
	m.lock.Lock()
	defer m.lock.Unlock()

	for _, device := range devices {
		if _, ok := m.devices[device.ID.String()]; ok {
			return ErrDeviceAlreadyExists(device.ID)
		}
	}

	for _, device := range devices {
		m.devices[device.ID.String()] = device
	}
	return nil
}

func (m *Memstore) ListDevicesByOwner(user uuid.ID, c context.Context) ([]Device, error) {
	var devices []Device
	for _, device := range m.devices {
		if !device.Owner.Equal(user) {
			continue
		}
		devices = append(devices, device)
	}
	return devices, nil
}
