User:Reedy/Airport Infobox Migration Plugin/Sources

/*
Copyright (C) 2008 Sam Reed

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using WikiFunctions;
using WikiFunctions.Plugin;

namespace Airport_Infobox_Migration_AWB_Plugin
{
    public class AirportInfoboxMigration : IAWBPlugin
    {
        private ToolStripMenuItem pluginenabledMenuItem = new ToolStripMenuItem("Airport Infobox Migration");
        OldInfoBox infobox;

        Regex AT = new Regex(@"\{\{\s*(?<tl>template\s*:)?\s*Airport title\b[\s\n\r]*(([\s\n\r]*\|[\s\n\r]*(?<parm>[^}{|\s\n\r=]*)[\s\n\r]*)+(=[\s\n\r]*(?<val>[^}{|\n\r]*)[\s\n\r]*)?)*\}\}[\s\n\r]*", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        Regex AI = new Regex(@"\{\{\s*(?<tl>template\s*:)?\s*Airport infobox\b[\s\n\r]*(([\s\n\r]*\|[\s\n\r]*(?<parm>[^}{|=]*)[\s\n\r]*)+(=[\s\n\r]*(?<val>[^}{|\n\r]*)[\s\n\r]*)?)*\}\}[\s\n\r]*", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        Regex RM = new Regex(@"\{\{\s*(?<tl>template\s*:)?\s*Runway\b[\s\n\r]*(([\s\n\r]*\|[\s\n\r]*(?<parm>[^}{|\s\n\r=]*)[\s\n\r]*)+(=[\s\n\r]*(?<val>[^}{|\n\r]*)[\s\n\r]*)?)*\}\}[\s\n\r]*", RegexOptions.IgnoreCase | RegexOptions.Compiled);

        #region IAWBPlugin Members

        public void Initialise(IAutoWikiBrowser MainForm)
        {
            pluginenabledMenuItem.CheckOnClick = true;
            MainForm.PluginsToolStripMenuItem.DropDownItems.Add(pluginenabledMenuItem);
        }

        public void LoadSettings(object[] prefs)
        {
            if (prefs == null) return;

            foreach (object o in prefs)
            {
                WikiFunctions.AWBSettings.PrefsKeyPair p = o as WikiFunctions.AWBSettings.PrefsKeyPair;
                if (p == null) continue;

                switch (p.Name.ToLower())
                {
                    case "enabled":
                        PluginEnabled = (bool)p.Setting;
                        break;
                }
            }
        }

        public string Name
        {
            get { return "Airport Infobox Migration Plugin"; }
        }

        public void Nudge(out bool Cancel)
        {
            Cancel = false;
        }

        public void Nudged(int Nudges)
        { }

        Regex AirportImageCommented = new Regex(@"<!--[\s\n\r]*\{\{Airport image[\s\n\r]*\|?[\s\n\r]*airport_image\s*=\s*([^\|\}]*)(\||\}\})[\s\n\r]*-->", RegexOptions.Compiled);
        Regex AirportImage = new Regex(@"\{\{Airport image[\s\n\r]*\|?[\s\n\r]*airport_image\s*=\s*([^\|\}]*)(\||\}\})", RegexOptions.Compiled);
        Regex noneNA = new Regex(@"(none|n/a)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        Regex AirportCoords = new Regex(@"[\s\n\r]*\|?[\s\n\r]*coordinates\s*=\s*\{\{(.*?)\}\}", RegexOptions.Compiled);
        Regex AirportLogo = new Regex(@"\|?logo_filename\s*=\s*([^\|\}]*)\|?", RegexOptions.Compiled);
        Regex AirportFAA = new Regex(@"(\[\[|\|)FAA\]\]: ([^\|\}]*)\s*", RegexOptions.Compiled);

        Regex AirportRunBy = new Regex(@"\|?\s*run by\s*=\s*\[\[(.*?)\]\]", RegexOptions.Compiled);
        Regex AirportClosestTown = new Regex(@"\|?\s*closest town\s*=\s*\[\[(.*?)\]\]", RegexOptions.Compiled);
        Regex AirportDistance = new Regex(@"\|?\s*distance\s*=\s*.*?[^|]?\r\n[^|]?", RegexOptions.Compiled);

        public string ProcessArticle(WikiFunctions.Plugin.IAutoWikiBrowser sender, WikiFunctions.Plugin.ProcessArticleEventArgs eventargs)
        {
            try
            {
                if (!PluginEnabled)
                    return eventargs.ArticleText;
                else if (eventargs.ArticleText.Contains("Infobox Airport"))
                {
                    eventargs.Skip = true;
                    sender.TraceManager.SkippedArticle(Name, "Article already contains {{Infobox Airport}}");
                    return eventargs.ArticleText;
                }
                else if (!eventargs.ArticleText.Contains("Airport infobox"))
                {
                    eventargs.Skip = true;
                    sender.TraceManager.SkippedArticle(Name, "Article doesn't contain {{Airport infobox}}");
                    return eventargs.ArticleText;
                }

                infobox = new OldInfoBox();

                string ArticleText = eventargs.ArticleText;

                Match AirportTitle = AT.Match(ArticleText);

                for (int p = 0; p < (AirportTitle.Groups["parm"].Captures.Count); p++)
                {
                    try
                    {
                        string parm = AirportTitle.Groups["parm"].Captures[p].Value.Trim();
                        string val = AirportTitle.Groups["val"].Captures[p].Value.Trim();

                        switch (parm)
                        {
                            case "name":
                                infobox.title = val;
                                break;
                            case "nativename":
                                infobox.native = val;
                                break;
                            case "nativename-a":
                                infobox.nativea = val;
                                break;
                            case "nativename-r":
                                infobox.nativer = val;
                                break;
                            default:
                                break;
                        }
                    }
                    catch { }
                }

                if (!AirportImageCommented.Match(ArticleText).Success)
                {
                    Match image = AirportImage.Match(ArticleText);
                    infobox.image = image.Groups[1].Value;
                    //infobox.size = image.Groups[2].Value;
                    //infobox.caption = image.Groups[3].Value;

                    infobox.logo = AirportLogo.Match(ArticleText).Groups[1].Value.Trim();
                }

                infobox.coords = AirportCoords.Match(ArticleText).Groups[1].Value;

                if (infobox.coords != "")
                {
                    ArticleText = ArticleText.Replace("{{" + infobox.coords + "}}", "");

                    infobox.coords = "{{" + infobox.coords;

                    if (!infobox.coords.Contains("|display=inline,title"))
                        infobox.coords += "|display=inline,title";

                    infobox.coords += "}}";

                    infobox.coords = infobox.coords.Replace("coor dms", "Coord");
                }

                if (AirportFAA.Match(ArticleText).Success)
                {
                    infobox.FAA = AirportFAA.Match(ArticleText).Groups[2].Value.Trim();
                    ArticleText = AirportFAA.Replace(ArticleText, "");
                }

                if (AirportRunBy.Match(ArticleText).Success)
                {
                    infobox.runby = "[[" + AirportRunBy.Match(ArticleText).Groups[1].Value.Trim() + "]]";
                    ArticleText = Regex.Replace(ArticleText, AirportRunBy.ToString(), "");
                }

                if (AirportClosestTown.Match(ArticleText).Success)
                {
                    infobox.nearest = "[[" + AirportClosestTown.Match(ArticleText).Groups[1].Value.Trim() + "]]";
                    ArticleText = Regex.Replace(ArticleText, AirportClosestTown.ToString(), "");
                }

                if (AirportDistance.Match(ArticleText).Success)
                {
                    ArticleText = Regex.Replace(ArticleText, AirportDistance.ToString(), "");
                }

                Match AirportInfobox = AI.Match(ArticleText);

                for (int r = 0; r < (AirportInfobox.Groups["parm"].Captures.Count); r++)
                {
                    try
                    {
                        string parm = AirportInfobox.Groups["parm"].Captures[r].Value.Trim();

                        string val = AirportInfobox.Groups["val"].Captures[r].Value.Trim();

                        switch (parm)
                        {
                            case "IATA":
                                infobox.IATA = RemoveNone(val);
                                break;
                            case "ICAO":
                                infobox.ICAO = RemoveNone(val.Replace("[[Location identifier", "").Replace("-", "")).Trim();
                                break;
                            case "LID":
                                infobox.LID = val;
                                break;
                            case "type":
                                infobox.type = Tools.TurnFirstToUpper(val);
                                break;
                            case "run by":
                                infobox.runby = val;
                                break;
                            case "closest town":
                                infobox.nearest = val;
                                break;
                            case "elevation_ft":
                                infobox.elft = val;
                                break;
                            case "elevation_m":
                                infobox.elm = val;
                                break;
                            //case "coordinates":
                            //    infobox.coords = val;
                            //    break;
                            case "website":
                                infobox.website = val;
                                break;
                            default:
                                break;
                        }
                    }
                    catch { }
                }

                MatchCollection RunwayMatch = RM.Matches(ArticleText);

                foreach (Match m in RunwayMatch)
                {
                    bool heli = false;
                    Heli hel = new Heli();
                    Runway run = new Runway();

                    for (int s = 0; s < (m.Groups["parm"].Captures.Count); s++)
                    {
                        try
                        {
                            string parm = m.Groups["parm"].Captures[s].Value.Trim();
                            string val = m.Groups["val"].Captures[s].Value.Trim().Replace("<center>", "").Replace("</center>", "");

                            if (parm == "runway_angle" && val.Contains("H"))
                                heli = true;

                            if (!heli)
                            {
                                switch (parm)
                                {
                                    case "runway_angle":
                                        run.angle = val;
                                        break;
                                    case "runway_length_f":
                                        run.ft = val;
                                        break;
                                    case "runway_length_m":
                                        run.m = val;
                                        break;
                                    case "runway_surface":
                                        if (val.Contains("[[") && !val.Contains("]]"))
                                            val += "]]";
                                        run.surface = val;
                                        break;
                                    default:
                                        break;
                                }
                            }
                            else
                            {
                                switch (parm)
                                {
                                    case "runway_angle":
                                        hel.no = val;
                                        break;
                                    case "runway_length_f":
                                        hel.ft = val;
                                        break;
                                    case "runway_length_m":
                                        hel.m = val;
                                        break;
                                    case "runway_surface":
                                        if (val.Contains("[[") && !val.Contains("]]"))
                                            val += "]]";
                                        hel.surface = val;
                                        break;
                                    default:
                                        break;
                                }
                            }
                        }
                        catch { }
                    }
                    if (heli)
                        infobox.heli.Add(hel);
                    else
                        infobox.runway.Add(run);

                }

                try
                {
                    ArticleText = ArticleText.Replace(WikiFunctions.Tools.StringBetween(ArticleText, "{{Airport frame}}", "{{Airport end frame}}"), formatNewTemplate()).Replace("{{Airport end frame}}", "");
                }
                catch
                {
                    ArticleText = ArticleText.Replace(WikiFunctions.Tools.StringBetween(ArticleText, "{{Airport frame}}", "{{End frame}}"), formatNewTemplate()).Replace("{{End frame}}", "");
                }

                ArticleText = Regex.Replace(ArticleText, "{{A.*{{Infobox Airport ", "{{Infobox Airport ");

                return ArticleText;
            }
            catch (Exception ex) { ErrorHandler.Handle(ex); return eventargs.ArticleText; }
        }

        private string RemoveNone(string Code)
        {
            return noneNA.Replace(Code, "");
        }

        public void Reset()
        {
            PluginEnabled = false;
        }

        public object[] SaveSettings()
        {
            WikiFunctions.AWBSettings.PrefsKeyPair[] pref = new WikiFunctions.AWBSettings.PrefsKeyPair[1];
            pref[0] = new WikiFunctions.AWBSettings.PrefsKeyPair("enabled", PluginEnabled);
            return pref;
        }

        public string WikiName
        {
            get { return "Airport Infobox Migration Plugin"; }
        }

        #endregion

        private string formatNewTemplate()
        {
            string newInfobox = @"{{Infobox Airport 
| name         = " + infobox.title;
            if (infobox.logo != "") newInfobox += @"
[[Image:" + infobox.logo + "]]";

            newInfobox += String.Format(@"
| nativename   = {0}
| nativename-a = {1}
| nativename-r = {2}
| image        = {3}
| image-width  = {4}
| caption      = {5}
| IATA         = {6}
| ICAO         = {7}
", infobox.native, infobox.nativea, infobox.nativer,
                  infobox.image, infobox.size, infobox.caption, infobox.IATA, infobox.ICAO);

            if (infobox.FAA != "") newInfobox += @"| FAA          = " + infobox.FAA + @"
";
            if (infobox.LID != "") newInfobox += @"| LID          = " + infobox.LID + @"
";

            newInfobox += String.Format(@"| type         = {0}
| owner        = {1}
| operator     = {2}
| city-served  = {3}
| location     = {4}
| elevation-f  = {5}
| elevation-m  = {6}
| coordinates  = {7}
| website      = {8}
| metric-elev  = {9}
| metric-rwy   = {10}", infobox.type, infobox.owner, infobox.runby, infobox.location, infobox.nearest,
                              infobox.elft, infobox.elm, infobox.coords, infobox.website, "", "");

            int i = 1;
            foreach (Runway run in infobox.runway)
            {
                newInfobox += string.Format(@"
| r{0}-number    = {1}
| r{0}-length-f  = {2}
| r{0}-length-m  = {3}
| r{0}-surface   = {4}", i, run.angle, run.ft, run.m, run.surface);

                i++;
            }

            i = 1;

            foreach (Heli hel in infobox.heli)
            {
                newInfobox += string.Format(@"
| h{0}-number    = {1}
| h{0}-length-f         = {2}
| h{0}-length-m         = {3}
| h{0}-surface   = {4}", i, hel.no, hel.ft, hel.m, hel.surface);

                i++;
            }

            newInfobox += @"
| stat-year    = 
| stat1-header = 
| stat1-data   = 
| stat2-header = 
| stat2-data   = 
| footnotes    = 
}}
";
            return newInfobox;
        }

        class OldInfoBox
        {
            public string title = "";
            public string native = "";
            public string nativea = "";
            public string nativer = "";
            public string image = "";
            public string size = "";
            public string caption = "";
            public string logo = "";
            public string IATA = "";
            public string ICAO = "";
            public string FAA = "";
            public string LID = "";
            public string type = "";
            public string owner = "";
            public string runby = "";
            public string nearest = "";
            public string location = "";
            public string elft = "";
            public string elm = "";
            public string coords = "";
            public string website = "";
            public List<Runway> runway = new List<Runway>();
            public List<Heli> heli = new List<Heli>();
        }

        class Runway
        {
            public string angle;
            public string m;
            public string ft;
            public string surface;
        }

        class Heli
        {
            public string no;
            public string m;
            public string ft;
            public string surface;
        }

        bool PluginEnabled
        {
            get { return pluginenabledMenuItem.Checked; }
            set { pluginenabledMenuItem.Checked = value; }
        }
    }
}