public static string GeneratePedanticCss(this CaliforniaProject californiaProject)
        {
            string cssStyleSheet = californiaProject.UserDefinedCss;

            foreach (var californiaView in californiaProject.CaliforniaViews.Where(v => !v.IsInternal.Value))
            {
                if (californiaView.UserDefinedCss != null)
                {
                    cssStyleSheet += californiaView.UserDefinedCss;
                }
            }
            if (californiaProject.UserDefinedCss != null)
            {
                cssStyleSheet += californiaProject.UserDefinedCss;
            }
            foreach (var responsiveDevice in californiaProject.ResponsiveDevices.OrderBy(r => r.WidthThreshold)) // TODO will switch around devices with same widththreshold (usually multiple with val==0)
            {
                string cssPerDevice = "";
                foreach (var styleMolecule in californiaProject.StyleMolecules) // TODO optimize query speed everywhere: this loop can be parallelized on SMP architecture
                {
                    GenerateAndAppendCss(styleMolecule, responsiveDevice, ref cssPerDevice);
                }
                cssPerDevice.WrapMediaQuery(responsiveDevice);
                if (cssPerDevice.Length > 0)
                {
                    cssStyleSheet += cssPerDevice;
                }
            }
            return(cssStyleSheet);
        }
        public static string GenerateJs(this CaliforniaProject californiaProject)
        {
            // TODO change class of html element and generate class css in css generator
            Dictionary <int, string> interactionDeclarationSnippets = new Dictionary <int, string>();
            Dictionary <int, string> interactionSnippetsForSwitch   = new Dictionary <int, string>();

            foreach (var interaction in californiaProject.LayoutStyleInteractions) // TODO generate code only for rendered interactions // TODO code duplication with client app
            {
                if (interaction.LayoutStyleInteractionType != LayoutStyleInteractionType.StyleToggle)
                {
                    throw new NotImplementedException();
                    // TODO scroll event interaction

                    /*window.addEventListener("scroll", function(evt: UIEvent): void {
                     *  console.log(((evt.target as HTMLDocument).scrollingElement as HTMLBodyElement).scrollTop + "," + ((evt.target as HTMLDocument).scrollingElement as HTMLBodyElement).scrollHeight);
                     * });*/
                }
                else
                {
                    string updatedCss          = "";
                    string restoredOrNulledCss = "";
                    foreach (var styleMap in interaction.StyleValueInteractions)
                    {
                        var elementFind = $"var el = document.getElementById(\"t{styleMap.StyleValue.StyleAtom.MappedToMolecule.StyleMolecule.StyleForLayoutId}\");\n";
                        updatedCss          += elementFind + $"el.style.setProperty(\"{styleMap.StyleValue.CssProperty}\", \"{styleMap.CssValue}\");";
                        restoredOrNulledCss += elementFind + $"el.style.setProperty(\"{styleMap.StyleValue.CssProperty}\", \"{styleMap.StyleValue.CssValue}\");";
                    }
                    var toggleVarName = $"t{interaction.LayoutAtomId}";
                    if (updatedCss.Length > 0 || restoredOrNulledCss.Length > 0)
                    {
                        interactionSnippetsForSwitch[interaction.LayoutStyleInteractionId] = $"if ({toggleVarName}) {{" +
                                                                                             $"{updatedCss}" +
                                                                                             $"}}" +
                                                                                             $"else {{" +
                                                                                             $"{restoredOrNulledCss}" +
                                                                                             $"}}\n" +
                                                                                             $"{toggleVarName} = !{toggleVarName};\n";
                        interactionDeclarationSnippets[interaction.LayoutStyleInteractionId] = toggleVarName;
                    }
                }
            }
            var publishedReloadIntervalMs = 10000;

            // same toggle routine for each interaction, path depends on element id
            return(string.Join("\n", interactionDeclarationSnippets.Select(varKvp => $"var {varKvp.Value}=true;")) +
                   $"var tar = \"\";\nvar ifn = function() {{\n" +
                   $"switch(tar) {{\n" +
                   string.Join("\n", interactionSnippetsForSwitch.Select(kvp => $"case \"{interactionDeclarationSnippets[kvp.Key]}\":\n{kvp.Value}\nbreak;")) +
                   $"default:\nbreak;\n" +
                   $"}};\n" + // end switch
                   $"}};\n" + // end function
                   "");       //$"setTimeout(function(){{location.reload();}}, {publishedReloadIntervalMs})\n"; // TODO reload triggered by backend (signalR or custom js)
        }