using System;
using System.Runtime;
using System.Runtime.InteropServices;
using GhostMono;

namespace gs_mono_example
{
	public partial class MainWindow
	{
		int m_firstpage;
		int m_lastpage;
        int m_current_page;
        Gtk.TreeIter m_tree_iter;

        /* For PDF optimization */
        private void PageRangeRender(int first_page, int last_page)
		{
			bool render_pages = false;
			for (int k = first_page; k <= last_page; k++)
			{
				if (m_docPages[k].Content != Page_Content_t.FULL_RESOLUTION)
				{
					render_pages = true;
					break;
				}
			}
			if (!render_pages)
				return;

			m_busy_render = true;
			m_firstpage = first_page;
			m_lastpage = last_page;
			//m_ghostscript.gsDisplayDeviceRender(m_currfile, first_page + 1, last_page + 1, 1.0);
		}

        /* Callback from ghostscript with the rendered image. */
        private void MainPageCallback(int width, int height, int raster, double zoom_in,
            int page_num, IntPtr data)
        {
            Byte[] bitmap = null;

            bitmap = new byte[raster * height];
            Marshal.Copy(data, bitmap, 0, raster * height);
            DocPage doc_page = m_docPages[m_current_page];

            if (doc_page.Content != Page_Content_t.FULL_RESOLUTION ||
                m_aa_change)
            {
                doc_page.Width = width;
                doc_page.Height = height;
                doc_page.Content = Page_Content_t.FULL_RESOLUTION;

                doc_page.Zoom = m_doczoom;
                doc_page.PixBuf = new Gdk.Pixbuf(bitmap,
                        Gdk.Colorspace.Rgb, false, 8, width,
                        height, raster);

                m_GtkimageStoreMain.SetValue(m_tree_iter, 0, doc_page.PixBuf);
            }

            if (page_num == 1)
                m_page_scroll_pos[0] = height;
            else
                m_page_scroll_pos[page_num - 1] = height + m_page_scroll_pos[page_num - 2];

            m_GtkimageStoreMain.IterNext(ref m_tree_iter);
            m_current_page += 1;
            m_GtkProgressBar.Fraction = ((double)page_num / ((double)page_num + 1));
            return;
        }

        private void RenderingDone()
		{
            if (m_firstime)
            {
                for (int k = 0; k < m_numpages; k++)
                {
                    pagesizes_t size = new pagesizes_t();
                    size.height = m_docPages[k].Height;
                    size.width = m_docPages[k].Width;
                    m_page_sizes.Add(size);
                }
            }

            m_aa_change = false;
            m_firstime = false;
            m_busy_render = false;

            /* Free up the large objects generated from the image pages.  If
             * this is not done, the application will run out of memory as
             * the user does repeated zoom or aa changes, generating more and
             * more pages without freeing previous ones.  The large object heap
             * is handled differently than other memory in terms of its GC */            
            GCSettings.LargeObjectHeapCompactionMode = 
                GCLargeObjectHeapCompactionMode.CompactOnce;
                GC.Collect();

            RemoveProgressBar();
            m_file_open = true;
            m_ghostscript.gsPageRenderedMain -= new ghostsharp.gsCallBackPageRenderedMain(gsPageRendered);
            m_GtkaaCheck.Sensitive = true;
            m_GtkZoomMinus.Sensitive = true;
            m_GtkZoomPlus.Sensitive = true;
        }

		/* Render all pages full resolution */
		private void RenderMainFirst()
		{
			m_firstpage = 1;
            m_current_page = 0;
            m_GtkimageStoreMain.GetIterFirst(out m_tree_iter);
            m_busy_render = true;
            m_ghostscript.gsPageRenderedMain += new ghostsharp.gsCallBackPageRenderedMain(gsPageRendered);
            AddProgressBar("Rendering Pages");
            m_ghostscript.gsDisplayDeviceRenderAll(m_currfile, m_doczoom, m_aa, GS_Task_t.DISPLAY_DEV_NON_PDF);
		}

		/* Render all, but only if not already busy,  called via zoom or aa changes */
		private void RenderMainAll()
		{
            try
            {
                if (!m_init_done)
                    return;
                m_GtkaaCheck.Sensitive = false;
                m_GtkZoomMinus.Sensitive = false;
                m_GtkZoomPlus.Sensitive = false;
                RenderMainFirst();
            }
            catch(Exception except)
            {
                var mess = except.Message;
            }
        }
	}
}