package com.jniwrapper.win32.hook.data;

import com.jniwrapper.*;
import com.jniwrapper.win32.hook.EventsFilter;
import com.jniwrapper.win32.ui.Wnd;

import java.util.List;

class EventsFilterStucture extends Structure
{
    private Int windowsCount = new Int();
    private PrimitiveArray windows = new PrimitiveArray(WindowStructure.class, EventsFilter.MAX_WINDOWS);
    private Int rangesCount = new Int();
    private PrimitiveArray ranges = new PrimitiveArray(RangeStructure.class, EventsFilter.MAX_RANGES);

    EventsFilterStucture()
    {
        init(new Parameter[]{windowsCount, windows, rangesCount, ranges}, (short) 1);
    }

    public void applyEventsFilter(EventsFilter filter)
    {
        if (filter == null)
        {
            throw new NullPointerException("Invalid events filter");
        }

        List windows = filter.getWindows();
        windowsCount.setValue(Math.min(windows.size(), EventsFilter.MAX_WINDOWS));
        for (int i = 0; i < EventsFilter.MAX_WINDOWS; i++)
        {
            if (i < windows.size())
            {
                EventsFilter.WindowRecord windowRecord = (EventsFilter.WindowRecord) windows.get(i);
                WindowStructure windowStructure = new WindowStructure(windowRecord);
                this.windows.setElement(i, windowStructure);
            }
            else
            {
                this.windows.setElement(i, new Wnd());
            }
        }

        List ranges = filter.getRanges();
        rangesCount.setValue(Math.min(ranges.size(), EventsFilter.MAX_RANGES));
        for (int i = 0; i < EventsFilter.MAX_RANGES; i++)
        {
            if (i < ranges.size())
            {
                EventsFilter.Range range = (EventsFilter.Range) ranges.get(i);
                RangeStructure rangeStructure = new RangeStructure(range);
                this.ranges.setElement(i, rangeStructure);
            }
            else
            {
                this.ranges.setElement(i, new RangeStructure());
            }
        }
    }

    protected static class WindowStructure extends Structure
    {
        private Wnd wnd = new Wnd();
        private Bool includeChildWindows = new Bool();

        public WindowStructure()
        {
            init(new Parameter[]{wnd, includeChildWindows}, (short) 1);
        }

        public WindowStructure(EventsFilter.WindowRecord windowRecord)
        {
            this();
            wnd.setValue(windowRecord.getWnd().getValue());
            includeChildWindows.setValue(windowRecord.isIncludeChildWindows());
        }

        public Wnd getWnd()
        {
            return wnd;
        }

        public Bool getIncludeChildWindows()
        {
            return includeChildWindows;
        }

        public Object clone()
        {
            WindowStructure clone = new WindowStructure();
            clone.initFrom(this);
            return clone;
        }
    }

    protected static class RangeStructure extends Structure
    {
        private Int lowerBound = new Int();
        private Int upperBound = new Int();

        public RangeStructure()
        {
            init(new Parameter[]{lowerBound, upperBound}, (short) 1);
        }

        public RangeStructure(int lowerBound, int upperBound)
        {
            this();
            this.lowerBound.setValue(lowerBound);
            this.upperBound.setValue(upperBound);
        }

        public RangeStructure(EventsFilter.Range range)
        {
            this(range.getLowerBound(), range.getUpperBound());
        }

        public Object clone()
        {
            RangeStructure clone = new RangeStructure();
            clone.initFrom(this);
            return clone;
        }
    }
}