using System;
//using System.CodeDom.Compiler;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;

// Creation date: 24.04.2002
// Checked: 04.11.2004
// Author: Otto Mayer (mot@root.ch)
// Version: 1.02

// Report.NET copyright 2002-2004 root-software ag, Bürglen Switzerland - Otto Mayer, Stefan Spirig, all rights reserved
// This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License

// as published by the Free Software Foundation, version 2.1 of the License.

// This library 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 Lesser General Public License for more details. You

// should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software

// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA www.opensource.org/licenses/lgpl-license.html

namespace Root.Reports {
  /// <summary>Report Tools Class</summary>
  public sealed class RT {
    //------------------------------------------------------------------------------------------02.11.2004
    #region Static
    //----------------------------------------------------------------------------------------------------

    /// <summary>Paper size A4 width in millimeters</summary>
    public const Double rA4_WidthMM = 210.224;

    /// <summary>Paper size A4 width in points (1/72 inch)</summary>
    public const Double rA4_Width = rA4_WidthMM * rMMToPoint;

    /// <summary>Paper size A4 height in millimeters</summary>
    public const Double rA4_HeightMM = 297.302;

    /// <summary>Paper size A4 height in points (1/72 inch)</summary>
    public const Double rA4_Height = rA4_HeightMM * rMMToPoint;

    /// <summary>Paper size A3 height in millimeters</summary>
    public const Double rA3_HeightMM = rA4_WidthMM * 2;

    //------------------------------------------------------------------------------------------28.06.2004
    /// <summary>Sets the number format for PDF values.</summary>
    static RT() {
      cultureInfo_PDF.NumberFormat.NumberDecimalSeparator = ".";
      #if (DEBUG)
      Double r = 1.2345;
      Debug.Assert(r.ToString(sPdfNumberFormat, cultureInfo_PDF) == "1.235");
      r = 0.5;
      Debug.Assert(r.ToString(sPdfNumberFormat, cultureInfo_PDF) == "0.5");
      #endif
    }

    //------------------------------------------------------------------------------------------28.06.2004
    /// <summary>Instances of this class are not allowed.</summary>
    private RT() {
    }

    //------------------------------------------------------------------------------------------30.06.2004
    /// <summary>Determines whether the specified numbers are considered equal.</summary>
    /// <param name="r1">First number to compare</param>
    /// <param name="r2">Second number to compare</param>
    /// <param name="rTolerance">Tolerance</param>
    /// <returns>true if r1 == r2 or if both numbers are <see cref="System.Double.NaN"/>; otherwise, false.</returns>
    public static Boolean bEquals(Double r1, Double r2, Double rTolerance) {
      if (Double.IsNaN(r1)) {
        return Double.IsNaN(r2);
      }
      if (Double.IsNaN(r2)) {
        return false;
      }
      return (Math.Abs(r1 - r2) < rTolerance);
    }
    #endregion

    //------------------------------------------------------------------------------------------02.11.2004
    #region Conversion
    //----------------------------------------------------------------------------------------------------

    /// <summary>Conversion factor: millimeter to point</summary>
    private const Double rMMToPoint = 1.0 / 25.4 * 72.0;

    /// <summary>Conversion factor: point to millimeter</summary>
    private const Double rPointToMM = 1.0 / 72.0 * 25.4;

    //------------------------------------------------------------------------------------------28.06.2004
    /// <summary>Converts millimeters to points (1/72 inch).</summary>
    /// <param name="rMM">Value in millimeters</param>
    /// <returns>value in points (1/72 inch)</returns>
    public static Double rPointFromMM(Double rMM) {
      return rMM * rMMToPoint;
    }

    //------------------------------------------------------------------------------------------28.06.2004
    /// <summary>Converts points (1/72 inch) to millimeters.</summary>
    /// <param name="rPoint">Value in points (1/72 inch)</param>
    /// <returns>value in millimeters</returns>
    public static Double rMMFromPoint(Double rPoint) {
      return rPoint * rPointToMM;
    }

    //------------------------------------------------------------------------------------------28.06.2004
    /// <summary>Converts degrees to radians.</summary>
    /// <param name="rDegree">Value in degrees</param>
    /// <returns>value in radians</returns>
    internal static Double rRadianFromDegree(Double rDegree) {
      Double r = Math.Floor(rDegree / 360.0) * 360.0;  // normalize angle
      rDegree = rDegree - r;
      return rDegree / 180.0 * Math.PI;
    }
    #endregion

    //------------------------------------------------------------------------------------------26.07.2004
    #region PDF
    //----------------------------------------------------------------------------------------------------

    /// <summary>Culture info for formatting PDF values</summary>
    private static System.Globalization.CultureInfo cultureInfo_PDF = new System.Globalization.CultureInfo("en-US");

    /// <summary>Number format string for PDF dimensions</summary>
    private const String sPdfNumberFormat = "0.###";

    //------------------------------------------------------------------------------------------28.06.2004
    /// <summary>Converts a dimension value to the PDF value format.</summary>
    /// <param name="rDim">Dimension value</param>
    /// <returns>Dimension value in the PDF value format</returns>
    internal static String sPdfDim(Double rDim) {
      return rDim.ToString(sPdfNumberFormat, cultureInfo_PDF);
    }

    //------------------------------------------------------------------------------------------04.11.2004
    /// <summary>StringBuilder object for use in "sPdfString"</summary>
    private static StringBuilder sb = new StringBuilder(200);

    /// <summary>Converts a string to the PDF text format.</summary>
    /// <param name="sText">String to convert to the PDF text format</param>
    /// <returns>String in the PDF text format</returns>
    internal static String sPdfString(String sText) {
      lock (sb) {
        sb.Length = 0;
        sb.Append('(');
        for (Int32 i = 0;  i < sText.Length;  i++) {
          Char c = sText[i];
          if (c == '(' || c == ')' || c == '\\') {
            sb.Append('\\');
          }
          sb.Append(c);
        }
        sb.Append(')');
        return sb.ToString();
      }
    }

    //------------------------------------------------------------------------------------------04.11.2004
    /// <summary>Shows the specified PDF document in a maximized window.</summary>
    /// <param name="sFileName">File name of the PDF document</param>
    public static void ViewPDF(String sFileName) {
      Microsoft.Win32.RegistryKey registryKey_Acro = 
        Microsoft.Win32.Registry.ClassesRoot.CreateSubKey("AcroExch.Document\\shell\\Open\\command");
      String sAcroPath = (String)registryKey_Acro.GetValue("");

      Process process = new Process();
      process.StartInfo.FileName = sAcroPath.Replace(" \"%1\"", "");
      process.StartInfo.Arguments = sFileName;
      process.StartInfo.WindowStyle = ProcessWindowStyle.Maximized;
      process.Start();
    }

    //------------------------------------------------------------------------------------------04.11.2004
    /// <summary>Shows the specified PDF document in a maximized window after that it has been created.</summary>
    /// <param name="report">Report object that creates the PDF document</param>
    /// <remarks>The PDF file will be stored in the current user's temporary folder.</remarks>
    public static void ViewPDF(Report report) {
      String sFileName = Path.GetTempFileName();
      report.Save(sFileName);
      ViewPDF(sFileName);
    }

    //------------------------------------------------------------------------------------------04.11.2004
    /// <summary>Shows the specified PDF document in a maximized window after that it has been created.</summary>
    /// <param name="report">Report object that creates the PDF document</param>
    /// <param name="sFileName">File name of the new PDF document</param>
    /// <remarks>
    /// If the specified file name is relative, the file will be created in the current user's temporary folder.
    /// If it exists, the name of the file will be made unique with a time stamp.
    /// If the specified file name is absolute, it will be overwritten if it exists.</remarks>
    public static void ViewPDF(Report report, String sFileName) {
      if (!Path.IsPathRooted(sFileName)) {
        sFileName = Path.Combine(Path.GetTempPath(), sFileName);
      }
      if (File.Exists(sFileName)) {
        String sDateTime = DateTime.Now.ToString("yyyyMMdd\\_HHmmss");
        String s = Path.GetFileNameWithoutExtension(sFileName) + "_" + sDateTime + Path.GetExtension(sFileName);
        sFileName = Path.Combine(Path.GetDirectoryName(sFileName), s);
      }
      else {
        Directory.CreateDirectory(Path.GetDirectoryName(sFileName));
      }
      report.Save(sFileName);
      ViewPDF(sFileName);
    }

    //------------------------------------------------------------------------------------------06.11.2004
    /// <summary>Prints the specified PDF document.</summary>
    /// <param name="sFileName">File name of the PDF document</param>
    public static void PrintPDF(String sFileName) {
      Microsoft.Win32.RegistryKey registryKey_Acro = 
        Microsoft.Win32.Registry.ClassesRoot.CreateSubKey("AcroExch.Document\\shell\\Open\\command");
      String sAcroPath = (String)registryKey_Acro.GetValue("");
      Process process = new Process();
      process.StartInfo.FileName = sAcroPath.Replace(" \"%1\"", "");
      process.StartInfo.Arguments = "/p /h " + sFileName;
      process.Start();
      // doesn't close the acrobat reader window
    }

    //------------------------------------------------------------------------------------------05.11.2004
    /// <summary>Prints the specified PDF document after that it has been created.</summary>
    /// <param name="report">Report object that creates the PDF document</param>
    public static void PrintPDF(Report report) {
      String sFileName = Path.GetTempFileName();
      report.Save(sFileName);
      PrintPDF(sFileName);
    }

    //------------------------------------------------------------------------------------------26.07.2004
    /// <summary>Sends the specified report to the browser.</summary>
    /// <param name="report">Report object that creates the PDF document</param>
    /// <param name="page">Page that has requested this report</param>
    public static void ResponsePDF(Report report, System.Web.UI.Page page) {
      page.Response.Clear();
      page.Response.ContentType = "application/pdf";

      if (!(report.formatter is PdfFormatter)) {
        throw new ReportException("PDF formatter required");
      }
      if (report.page_Cur == null) {
        report.Create();
      }

      report.formatter.Create(report, page.Response.OutputStream);
      page.Response.End();
    }
    #endregion

    //------------------------------------------------------------------------------------------02.11.2004
    #region Obsolete
    //----------------------------------------------------------------------------------------------------

    /// <summary>Conversion factor: millimeter to point</summary>
    [Obsolete("use method: Double rPointFromMM(Double rMM)")]
    public const Double rMM_To_I72 = 1.0 / 25.4 * 72.0;

    /// <summary>Conversion factor: point to millimeter</summary>
    [Obsolete("use method: Double rMMFromPoint(Double rPoint)")]
    public const Double rI72_To_MM = 1.0 / 72.0 * 25.4;

    //------------------------------------------------------------------------------------------28.06.2004
    /// <summary>Converts millimeters to points (1/72 inch).</summary>
    /// <param name="rMM">value in millimeters</param>
    /// <returns>value in points (1/72 inch)</returns>
    [Obsolete("use method: Double rPointFromMM(Double rMM)")]
    public static Double rMM(Double rMM) {
      return rMM * rMM_To_I72;
    }

    //------------------------------------------------------------------------------------------02.08.2004
    /// <summary>Sends the specified report to the browser.</summary>
    /// <param name="report">Report object that creates the PDF document</param>
    /// <param name="response">Response stream</param>
    [Obsolete("use method: ResponsePDF(Report, Page)")]
    public static void ResponsePDF(Report report, System.Web.HttpResponse response) {
      if (report.formatter == null) {
        report.Init(new PdfFormatter());
      }
      if (report.page_Cur == null) {
        report.Create();
      }
      response.ClearContent();
      response.ContentType = "application/pdf";
      MemoryStream ms = new MemoryStream(20000);
      report.formatter.Create(report, ms);
      ms.Close();

      response.BinaryWrite(ms.GetBuffer());
      response.End();
    }
    #endregion
  }
}
