sftblw/Webpage-Sidebar

View on GitHub
src/common/siteState.ts

Summary

Maintainability
A
35 mins
Test Coverage
import { MappedList, LimitedMappedList } from './mappedList';
import { CrudStamp } from './crudStamp';
import { Site } from './site';

export class SiteState {
    private _siteList: MappedList<string, Site> = new MappedList((site: Site) => site.key);

    get siteListReadonly(): ReadonlyArray<Site> {
        return this._siteList.readOnlyList;
    }
    set siteList(val: Array<Site>) {
        this._siteList.list = val;
    }

    private _deletedSiteList: LimitedMappedList<string, CrudStamp> = new LimitedMappedList(
        64,
        (stamp: CrudStamp) => Site.KeyFromCrud(stamp),
        (item1: CrudStamp, item2: CrudStamp): number => {
            if (item1.d === undefined || item2.d === undefined) {
                throw "item should have deleted date string";
            }
            let item1D = new Date(item1.d);
            let item2D = new Date(item2.d);

            // order by recent
            return (item1D > item2D) ? 1 : 0; // more recent -> bigger -> lesser index
        });

    get deletedSiteList(): Array<CrudStamp> {
        return this._deletedSiteList.list;
    }

    // version
    v: string = '0.1.0';
    static curVer: string = '0.1.0'; // for checking

    constructor() { }

    addSite(site: Site) {
        this._siteList.add(site);
    }

    removeSite(site: Site) {
        let oldSite = this._siteList.get(site);

        if (oldSite === undefined) { throw "site does not exist"; }

        oldSite.d.d = new Date().toISOString();

        delete oldSite.d.u;

        this._deletedSiteList.add(oldSite.d);
        this._siteList.remove(oldSite);
    }

    static migrateOrCreate(siteState: SiteState | Array<object> | undefined | null): SiteState {
        if (siteState === null || typeof siteState === "undefined") {
            return new SiteState();
        }

        let curSiteState: SiteState;

        // migrate from 0.0.x
        if (Array.isArray(siteState)) {
            let sl = new SiteState();
            for (var siteObj of <Array<object>>siteState) {
                sl.addSite(new Site((<any>siteObj).url));
            }

            curSiteState = sl;
        } else {
            curSiteState = siteState;
        }

        curSiteState = SiteState.FromObject(curSiteState);

        while (curSiteState.v != this.curVer) {
            // do migrate
        }

        return curSiteState;
    }

    /**
     * merges siteState into this
     * @param siteState to merge with this
     */
    mergeWith(siteState: SiteState): SiteState {
        // merge sitelist
        siteState.siteListReadonly.forEach(site => {
            let thisSite = this._siteList.get(site);

            if (thisSite !== undefined) {
                if (site.d.u === undefined || thisSite.d.u === undefined) {
                    throw 'site should have always updated date';
                }

                // update
                if (new Date(thisSite.d.u) < new Date(site.d.u)) {
                    this._siteList.remove(thisSite);
                    this._siteList.add(site);
                }
            }
            // add
            else {
                this._siteList.add(site);
            }
        });

        // merge deleted list
        siteState.deletedSiteList.forEach(crud => {
            if (this._deletedSiteList.get(crud) === undefined) {
                this._siteList.removeByKey(Site.KeyFromCrud(crud));
                this._deletedSiteList.add(crud);
            }
        });

        // strip out deleted list
        this._deletedSiteList.list.forEach(crud => {
            this._siteList.removeByKey(Site.KeyFromCrud(crud));
        });

        return this;
    }

    static FromObject(siteState: object): SiteState {
        if (siteState instanceof SiteState) { return siteState; }

        let newObj = new SiteState();
        let _siteList = newObj._siteList;
        let _deletedSiteList = newObj._deletedSiteList;

        newObj = Object.assign(newObj, siteState);

        newObj._siteList = _siteList;
        newObj._siteList.list = ((siteState as any)._siteList as Array<object>).map(site => Site.FromObject(site));

        newObj._deletedSiteList = _deletedSiteList;
        newObj._deletedSiteList.list = (siteState as any)._deletedSiteList;

        return newObj;
    }

    toObject() {
        let newObj = Object.assign({}, this);

        newObj._siteList = this._siteList.list as any;
        newObj._deletedSiteList = this._deletedSiteList.list as any;

        return newObj;
    }
}