// Package: com.lightningkite.ktordb
// Generated by Khrysalis - this file will be overwritten.

//! Declares com.lightningkite.ktordb.Aggregate
export class Aggregate {
    private constructor(name: string, jsonName: string) {
        this.name = name;
        this.jsonName = jsonName;
    }
    
    public static Sum = new Aggregate("Sum", "Sum");
    
    public static Average = new Aggregate("Average", "Average");
    
    public static StandardDeviationSample = new Aggregate("StandardDeviationSample", "StandardDeviationSample");
    
    public static StandardDeviationPopulation = new Aggregate("StandardDeviationPopulation", "StandardDeviationPopulation");
    
    private static _values: Array<Aggregate> = [Aggregate.Sum, Aggregate.Average, Aggregate.StandardDeviationSample, Aggregate.StandardDeviationPopulation];
    public static values(): Array<Aggregate> { return Aggregate._values; }
    public readonly name: string;
    public readonly jsonName: string;
    public static valueOf(name: string): Aggregate { return (Aggregate as any)[name]; }
    public toString(): string { return this.name }
    public toJSON(): string { return this.jsonName }
    public static fromJSON(key: string): Aggregate { return Aggregate._values.find(x => x.jsonName.toLowerCase() === key.toLowerCase())! }
}

//! Declares com.lightningkite.ktordb.aggregator>com.lightningkite.ktordb.Aggregate
export function xAggregateAggregator(this_: Aggregate): Aggregator {
    return ((): Aggregator => {
        switch(this_) {
            case Aggregate.Sum: {
                return new SumAggregator()
            }
            case Aggregate.Average: {
                return new AverageAggregator()
            }
            case Aggregate.StandardDeviationSample: {
                return new StandardDeviationSampleAggregator()
            }
            case Aggregate.StandardDeviationPopulation: {
                return new StandardDeviationPopulationAggregator()
            }
            default:
        throw new Error("Exhaustive when turned out to not be so exhaustive.")}
        
    })();
}

//! Declares com.lightningkite.ktordb.Aggregator
export interface Aggregator {
    
    consume(value: number): void
    complete(): (number | null)
}


//! Declares com.lightningkite.ktordb.SumAggregator
export class SumAggregator implements Aggregator {
    public static implementsAggregator = true;
    public constructor() {
        this.current = 0.0;
        this.anyFound = false;
    }
    
    public current: number;
    public anyFound: boolean;
    public consume(value: number): void {
        this.anyFound = true;
        this.current = this.current + value;
    }
    public complete(): (number | null) {
        return this.anyFound ? this.current : null;
    }
}
//! Declares com.lightningkite.ktordb.AverageAggregator
export class AverageAggregator implements Aggregator {
    public static implementsAggregator = true;
    public constructor() {
        this.count = 0;
        this.current = 0.0;
    }
    
    public count: number;
    public current: number;
    public consume(value: number): void {
        this.count = this.count + 1;
        this.current = this.current + (value - this.current) / this.count;
    }
    public complete(): (number | null) {
        return this.count === 0 ? null : this.current;
    }
}
//! Declares com.lightningkite.ktordb.StandardDeviationSampleAggregator
export class StandardDeviationSampleAggregator implements Aggregator {
    public static implementsAggregator = true;
    public constructor() {
        this.count = 0;
        this.mean = 0.0;
        this.m2 = 0.0;
    }
    
    public count: number;
    public mean: number;
    public m2: number;
    public consume(value: number): void {
        this.count = this.count + 1;
        const delta1 = value - this.mean;
        this.mean = this.mean + (delta1) / this.count;
        const delta2 = value - this.mean;
        this.m2 = this.m2 + delta1 * delta2;
    }
    public complete(): (number | null) {
        return this.count < 2 ? null : Math.sqrt(this.m2 / (this.count - 1));
    }
}
//! Declares com.lightningkite.ktordb.StandardDeviationPopulationAggregator
export class StandardDeviationPopulationAggregator implements Aggregator {
    public static implementsAggregator = true;
    public constructor() {
        this.count = 0;
        this.mean = 0.0;
        this.m2 = 0.0;
    }
    
    public count: number;
    public mean: number;
    public m2: number;
    public consume(value: number): void {
        this.count = this.count + 1;
        const delta1 = value - this.mean;
        this.mean = this.mean + (delta1) / this.count;
        const delta2 = value - this.mean;
        this.m2 = this.m2 + delta1 * delta2;
    }
    public complete(): (number | null) {
        return this.count === 0 ? null : Math.sqrt(this.m2 / this.count);
    }
}

//! Declares com.lightningkite.ktordb.aggregate>kotlin.sequences.Sequencekotlin.Double
export function xSequenceAggregate(this_: Iterable<number>, aggregate: Aggregate): (number | null) {
    const aggregator = xAggregateAggregator(aggregate);
    for (const item of this_) {
        aggregator.consume(item);
    }
    return aggregator.complete();
}
