// country lables make 95% of the size of the file !!! therefore this attempts to reduce this a bit
        //
        // EM2 STRUCTURE: each variable has n structures of the form below for n countries that describe the variable:
        // <CountryLabel> <ID>...</ID><VariableID>...</VariableID><Country>..</Country><Label>...</Label></CountryLabel>
        //
        // EM3 STRUCTURE (per variable): <Labels><![CDATA[c1°c1-lable|c2°c2-label|...]]></Labels> (note: CDATA only once required)
        // e.g. <Labels><![CDATA[bg°Unemployment benefit (обезщетениe за безработица)|cy°Unemployment benefits from Social Insurance Fund|dk°Unemployment benefits and similar benefits (Arbejdsløshedsdagpenge og andre A- kasseydelser)|ee°unemployment insurance benefit (töötukindlustushüvitis)|el°unemployment insurance benefit (επίδομα ανεργίας)|es°Unemployment insurance (Prestación por desempleo)|fi°Earnings-related unemployment allowance|fr°Contributory unemployment benefit (ARE)|ie°jobseekers benefit (mainly)|lt°unemployment insurance benefit (nedarbo draudimo išmoka)|pt°benefit : unemployment : contributory|si°unemployment wage compensation (denarno nadomestilo za primer brezposelnosti)|sk°Contributory unemployment benefit|uk°JSA contributory|HR°unemployment benefit]]></Labels>
        //
        // note: this is a bit against our principle to keep things separate and avoid complicated string-constructs,
        // but perhaps it is justified by the reduction in size of the variables file ...
        // KOSTAS - T O D O (low priority): rethink this structure
        private Dictionary <string, string> ShortLabels(EM2Variables.Content content)
        {
            Dictionary <string, string> varCountryLabels = new Dictionary <string, string>();

            foreach (var lab in content.countryLabels)
            {
                if (lab[EM2TAGS.LABEL] == XmlHelpers.CDATA() ||
                    lab[EM2TAGS.LABEL] == XmlHelpers.CDATA("-"))
                {
                    continue;                                              // empty
                }
                string varID = lab[EM2TAGS.VAR_ID];
                string label = XmlHelpers.RemoveCData(lab[EM2TAGS.LABEL]);
                if (!varCountryLabels.ContainsKey(varID))
                {
                    varCountryLabels.Add(varID, string.Empty);
                }
                else
                {
                    varCountryLabels[varID] += "|";
                }
                varCountryLabels[varID] += $"{lab[EM2TAGS.COUNTRY]}°{label}";
            }
            return(varCountryLabels);
        }
        /// <summary>
        /// reads the EM2 variables file and transfers it to EM3 style
        /// creates the config folder, if it does not exist, and overwrites any existing variables file
        /// note: the intended usage is "single variables transformation"
        ///       the EM3All class is responsible for complete EM-content transformation (using the EM3Variables.Write functions)
        /// </summary>
        /// <param name="emPath"> EuromodFiles folder (containing EM2-files in XMLParam and (will contain) EM3-files in EM3Translation\XMLParam) </param>
        /// <param name="errors"> critical and non-critical erros during the transformation-process, empty structure for no errors </param>
        public static bool Transform(string emPath, out List <string> errors)
        {
            errors = new List <string>(); EMPath pathHandler = new EMPath(emPath);
            try
            {
                DirectoryInfo di = Directory.CreateDirectory(pathHandler.GetFolderConfig());

                if (TransformerCommon.IsFileUpToDate(pathHandler.GetVarFilePath(em2: true), di.FullName, out string hashCode))
                {
                    return(true);
                }

                // read EM2-file
                EM2Variables.Content content = EM2Variables.Read(pathHandler.GetFolderConfig(em2: true), out List <string> rErrors);
                if (content == null)
                {
                    errors = rErrors; return(false);
                }

                // transfer to EM3-structure
                bool success = Write(content, emPath, out List <string> wErrors);
                errors.AddRange(wErrors);

                if (success && errors.Count == 0)
                {
                    TransformerCommon.WriteUpToDate(pathHandler.GetVarFilePath(em2: true), di.FullName, hashCode);
                }
                return(success);
            }
            catch (Exception exception)
            {
                errors.Add($"Variables: {exception.Message}");
                return(false);
            }
        }
        /// <summary> performs all EM2->EM3 adaptations for the variables file </summary>
        /// <in_out param name="content"> content of file as read by EM2Variables.Read </param>
        internal void AdaptVar(EM2Variables.Content content)
        {
            Dictionary <string, string> varCountryLabels = ShortLabels(content); // see below

            foreach (var v in content.variables)
            {
                // AutoLabel not necessary (was just stored for performance reasons in Excel-UI)
                v.Remove(EM2TAGS.AUTO_LABEL);

                // add the compressed labels to the variable, if there are labels (see below)
                if (varCountryLabels.ContainsKey(v[EM2TAGS.ID]))
                {
                    v.Add(EM_XmlHandler.TAGS.LABELS, XmlHelpers.CDATA(varCountryLabels[v[EM2TAGS.ID]]));
                }
            }
        }
        /// <summary>
        /// transfers the EM2 variables file into EM3 style and creates the respective EM3 file
        /// note: this class is only responsible for writing, EM2->EM3 adaptations are accomplished by a call to the EM23Adapt class
        /// also note: the function is not intended to be used "stand-alone", but by EM3Variables.Transform and EM3All.Write
        /// </summary>
        /// <param name="content"> content of variables-file as read by EM2Variables.Read </param>
        /// <param name="emPath"> EuromodFiles folder (containing EM2-files in XMLParam and (will contain) EM3-files in EM3Translation\XMLParam) </param>
        /// <param name="errors"> critical and non-critical erros during the write-process, empty structure for no errors </param>
        public static bool Write(EM2Variables.Content content, string emPath, out List <string> errors)
        {
            errors = new List <string>();
            XmlWriter writer;

            try
            {
                (new EM23Adapt()).AdaptVar(content); // adapt from EM2 style to EM3 style

                using (writer = XmlWriter.Create(new EMPath(emPath).GetVarFilePath(), TransformerCommon.GetXmlWriterSettings()))
                {
                    writer.WriteStartElement(TransformerCommon.ROOT_ELEMENT);
                    WriteList(TAGS.VAR, content.variables);
                    WriteList(TAGS.ACTYPE, content.acroTypes);
                    WriteList(TAGS.ACLEVEL, content.acroLevels);
                    WriteList(TAGS.ACRO, content.acros);
                    WriteList(TAGS.CAT, content.acroCategories);
                    writer.WriteEndElement();
                    return(true);
                }
            }
            catch (Exception exception)
            {
                errors.Add($"Variables: {exception.Message}");
                return(false);
            }

            void WriteList(string tag, List <Dictionary <string, string> > items)
            {
                writer.WriteStartElement(TAGS.Enclosure(tag));
                foreach (var item in items)
                {
                    writer.WriteStartElement(tag);
                    foreach (var p in item)
                    {
                        TransformerCommon.TranslateAndWriteElement(writer, p.Key, p.Value, tag);
                    }
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();
            }
        }