//ライセンス情報はAgeOnフォルダのLISENCEフォルダを参照してください
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Diagnostics;
using System.Net;
using System.IO;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

namespace nispi
{
    class BitmapSets
    {
        public Bitmap fillBitmap;
        public Bitmap pointBitmap;
        public Bitmap synthesisBitmap;

        public BitmapSets(Bitmap fillBitmap, Bitmap pointBitmap, Bitmap synthesisBitmap)
        {
            this.fillBitmap = fillBitmap;
            this.pointBitmap = pointBitmap;
            this.synthesisBitmap = synthesisBitmap;
        }
    }
    class DrawToMap
    {
        private long maxPixelPoint;

        public DrawToMap()
        {
        }

        public Bitmap DrawMarkPoint(Bitmap frontBitmap, List<Point> addMapMarkPoint, byte Green, byte Red, byte Blue)
        {
            Brush brush = new SolidBrush(Color.FromArgb(255, Red, Green, Blue));
            Brush brush2 = new SolidBrush(Color.FromArgb(0xFF, 0x01, 0x01, 0x01));
            Graphics g = Graphics.FromImage(frontBitmap);

            foreach (Point point in addMapMarkPoint)
            {
                //円を描画する
                g.FillPie(brush, point.X - 5, point.Y - 5, 10, 10, 0, 360);
                g.DrawArc(new Pen(brush2), point.X - 5, point.Y - 5, 10, 10, 0, 360);
            }

            //リソースを解放する
            g.Dispose();
            brush.Dispose();
            brush2.Dispose();

            return frontBitmap;
        }

        public Bitmap DrawMarkPointList(Bitmap frontBitmap, List<MarkPointInfo> mapMarkPointList, byte Red, byte Blue)
        {
            Brush brush = new SolidBrush(Color.FromArgb(255, Red, 255, Blue));
            Brush brush2 = new SolidBrush(Color.FromArgb(0xFF, 0x01, 0x01, 0x01));
            Graphics g = Graphics.FromImage(frontBitmap);

            foreach (MarkPointInfo markPointInfo in mapMarkPointList)
            {
                brush.Dispose();
                brush = new SolidBrush(Color.FromArgb(255, Red, markPointInfo.powerNum, Blue));
                foreach (Point point in markPointInfo.list)
                {
                    //円を描画する
                    g.FillPie(brush, point.X - 5, point.Y - 5, 10, 10, 0, 360);
                    g.DrawArc(new Pen(brush2), point.X - 5, point.Y - 5, 10, 10, 0, 360);
                }
            }
            //リソースを解放する
            g.Dispose();
            brush.Dispose();
            brush2.Dispose();

            return frontBitmap;
        }

        public Bitmap DrawCruciformPoint(Bitmap frontBitmap, List<Point> pointList, byte Red, byte Green, byte Blue)
        {
            //Listより速く小さなリストおよび配列構造を選択
            List<Point> newPointList = new List<Point>();
            List<Point> tempPointList = new List<Point>();

            //ピクセル単位の配列を準備
            int w = frontBitmap.Width;
            int h = frontBitmap.Height;
            Bitmap newFrontBmp = new Bitmap(w, h);
            BitmapData frontBmpd, newBmpd;
            byte[] frontPixels;
            long pixelsize;

            //表の図。描画を行う
            frontBmpd = frontBitmap.LockBits(new Rectangle(0, 0, w, h),
                ImageLockMode.ReadOnly,
                PixelFormat.Format32bppArgb);
            newBmpd = newFrontBmp.LockBits(new Rectangle(0, 0, w, h),
                ImageLockMode.WriteOnly,
                PixelFormat.Format32bppArgb);

            pixelsize = w * h * 4;
            maxPixelPoint = pixelsize;

            frontPixels = new byte[pixelsize];
            Marshal.Copy(frontBmpd.Scan0, frontPixels, 0, frontPixels.Length);

            try
            {
                while (true)
                {
                    foreach (Point point in pointList)
                    {
                        //
                        int topPoint = (point.X * 4) + (w * 4 * (point.Y + 1));
                        int bottomPoint = (point.X * 4) + (w * 4 * (point.Y - 1));
                        int rightPoint = ((point.X + 1) * 4) + (w * 4 * point.Y);
                        int leftPoint = ((point.X - 1) * 4) + (w * 4 * point.Y);

                        //上
                        if (true == CheckColor(frontPixels, topPoint, Red, Green, Blue))
                            newPointList.Add(new Point(point.X, point.Y + 1));
                        //下
                        if (true == CheckColor(frontPixels, bottomPoint, Red, Green, Blue))
                            newPointList.Add(new Point(point.X, point.Y - 1));
                        //右
                        if (true == CheckColor(frontPixels, rightPoint, Red, Green, Blue))
                            newPointList.Add(new Point(point.X + 1, point.Y));
                        //左
                        if (true == CheckColor(frontPixels, leftPoint, Red, Green, Blue))
                            newPointList.Add(new Point(point.X - 1, point.Y));
                    }
                    pointList.Clear();
                    tempPointList = pointList;
                    pointList = newPointList;
                    newPointList = tempPointList;

                    if (pointList.Count == 0)
                        break;
                }
            }

            catch (System.Exception ex)
            {
                Const.debugForm.OutPutDebug("Map", ex);

                //テータ解放必要
                return frontBitmap;
            }

            Marshal.Copy(frontPixels, 0, newBmpd.Scan0, frontPixels.Length);

            //表のメモリ解放
            frontBitmap.UnlockBits(frontBmpd);
            //新しいデータの目盛解放
            newFrontBmp.UnlockBits(newBmpd);

            return newFrontBmp;
        }

        public Bitmap DrawCruciformPointList(Bitmap frontBitmap, List<FillPointInfo> fillPointInfoList, byte Red, byte Blue)
        {
            List<Point> newPointList = new List<Point>();
            List<Point> tempPointList = new List<Point>();

            //ピクセル単位の配列を準備
            int w = frontBitmap.Width;
            int h = frontBitmap.Height;
            Bitmap newFrontBmp = new Bitmap(w, h);
            BitmapData frontBmpd, newBmpd;
            byte[] frontPixels;
            long pixelsize;

            //表の図。描画を行う
            frontBmpd = frontBitmap.LockBits(new Rectangle(0, 0, w, h),
                ImageLockMode.ReadOnly,
                PixelFormat.Format32bppArgb);
            newBmpd = newFrontBmp.LockBits(new Rectangle(0, 0, w, h),
                ImageLockMode.WriteOnly,
                PixelFormat.Format32bppArgb);

            pixelsize = w * h * 4;
            maxPixelPoint = pixelsize;

            frontPixels = new byte[pixelsize];
            Marshal.Copy(frontBmpd.Scan0, frontPixels, 0, frontPixels.Length);

            try
            {
                foreach (FillPointInfo fillPointInfo in fillPointInfoList)
                {
                    byte Green = fillPointInfo.powerNum;
                    while (true)
                    {
                        foreach (Point point in fillPointInfo.list)
                        {
                            //
                            int topPoint = (point.X * 4) + (w * 4 * (point.Y + 1));
                            int bottomPoint = (point.X * 4) + (w * 4 * (point.Y - 1));
                            int rightPoint = ((point.X + 1) * 4) + (w * 4 * point.Y);
                            int leftPoint = ((point.X - 1) * 4) + (w * 4 * point.Y);

                            //上
                            if (true == CheckColor(frontPixels, topPoint, Red, Green, Blue))
                                newPointList.Add(new Point(point.X, point.Y + 1));
                            //下
                            if (true == CheckColor(frontPixels, bottomPoint, Red, Green, Blue))
                                newPointList.Add(new Point(point.X, point.Y - 1));
                            //右
                            if (true == CheckColor(frontPixels, rightPoint, Red, Green, Blue))
                                newPointList.Add(new Point(point.X + 1, point.Y));
                            //左
                            if (true == CheckColor(frontPixels, leftPoint, Red, Green, Blue))
                                newPointList.Add(new Point(point.X - 1, point.Y));
                        }
                        fillPointInfo.list.Clear();
                        tempPointList = fillPointInfo.list;
                        fillPointInfo.list = newPointList;
                        newPointList = tempPointList;

                        if (fillPointInfo.list.Count == 0)
                            break;
                    }
                }
            }
            catch (System.Exception ex)
            {
                Const.debugForm.OutPutDebug("Map", ex);
                return frontBitmap;
            }
            Marshal.Copy(frontPixels, 0, newBmpd.Scan0, frontPixels.Length);

            //表のメモリ解放
            frontBitmap.UnlockBits(frontBmpd);
            //新しいデータの目盛解放
            newFrontBmp.UnlockBits(newBmpd);

            return newFrontBmp;
        }

        bool CheckColor(byte[] frontPixels, int pixelPoint, byte Red, byte Green, byte Blue)
        {
            //try節で速度低下の可能性
            try
            {
                if ((pixelPoint > maxPixelPoint) || (pixelPoint < 0))
                    return false;

                byte B = frontPixels[pixelPoint];
                byte G = frontPixels[1 + pixelPoint];
                byte R = frontPixels[2 + pixelPoint];

                if (((R == 0) && (G == 0) && (B == 0)) ||
                    ((R == 150) && (G == 150) && (B == 150)) ||
                    ((R == 153) && (G == 217) && (B == 234)) ||
                    ((R == Red) && (G == Green) && (B == Blue)))
                {
                    return false;
                }
                else
                {
                    //塗りつぶす
                    frontPixels[pixelPoint] = Blue;
                    frontPixels[1 + pixelPoint] = Green;
                    frontPixels[2 + pixelPoint] = Red;
                    frontPixels[3 + pixelPoint] = 255;

                    return true;
                }
            }
            catch (System.Exception ex)
            {
                Const.debugForm.OutPutDebug("Map", ex);
                return false;
            }
        }
    }
}